home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / c / minigl.lha / MiniGL / src / draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-03  |  75.4 KB  |  3,834 lines

  1. /*
  2.  * $Id: draw.c,v 1.4 2001/02/01 14:36:49 tfrieden Exp $
  3.  *
  4.  * $Date: 2001/02/01 14:36:49 $
  5.  * $Revision: 1.4 $
  6.  *
  7.  * (C) 1999 by Hyperion
  8.  * All rights reserved
  9.  *
  10.  * This file is part of the MiniGL library project
  11.  * See the file Licence.txt for more details
  12.  *
  13.  */
  14.  
  15.  
  16. // Surgeon: Polygon clip/reject tests:
  17. // Primary bottleneck on 68060 is CPU/FPU.
  18. // On PPC it is more often bandwidth/fillrate.
  19. // The following define adjusts level of rejection-tests
  20.  
  21. #define PRIORITIZE_BANDWIDTH 1
  22.  
  23. #ifdef __PPC__ 
  24. #define PRIORITIZE_FILLRATE  1
  25. #endif
  26.  
  27.  
  28. #include "sysinc.h"
  29. #include "vertexarray.h"
  30.  
  31. #include <math.h>
  32.  
  33. #include <stdlib.h>
  34. #ifdef __VBCC__
  35. #include <stdio.h>
  36. #endif
  37.  
  38. #ifdef DISABLE_TRANSFORMATION
  39. #warning "Compiling without transformation pipeline. Only flat geometry supported"
  40. #endif
  41.  
  42. static char rcsid[] = "$Id: draw.c,v 1.4 2001/02/01 14:36:49 tfrieden Exp $";
  43.  
  44. #define DUMP_VERTEX2(vert)
  45.  
  46. //for multitexturing:
  47. extern void TMA_Start(LockTimeHandle *handle);
  48. extern GLboolean TMA_Check(LockTimeHandle *handle);
  49. extern void fog_Set(GLcontext context);
  50.  
  51.  
  52. void d_DrawPoly(GLcontext context, MGLPolygon *poly);
  53. void dh_DrawPolyFF(GLcontext context, MGLPolygon *poly);
  54. void d_DrawPoints        (GLcontext);
  55. void d_DrawLines         (GLcontext);
  56. void d_DrawLineStrip     (GLcontext);
  57. void d_DrawTriangles     (GLcontext);
  58. void d_DrawTriangleFan   (GLcontext);
  59. void d_DrawTriangleStrip (GLcontext);
  60. void d_DrawQuads         (GLcontext);
  61. void d_DrawFixPoly       (GLcontext);
  62. void d_DrawMtexPoly      (GLcontext);
  63. void d_DrawSmoothPoly    (GLcontext);
  64. void d_DrawNormalPoly    (GLcontext);
  65. void d_DrawQuadStrip     (GLcontext);
  66. void d_DrawTrianglesVA   (GLcontext); //Surgeon
  67. void d_DrawFlat       (GLcontext);
  68.  
  69. #if 0
  70. void d_DrawFlatFan       (GLcontext);
  71. void d_DrawFlatStrip     (GLcontext);
  72. #endif
  73.  
  74.  
  75. INLINE GLvoid v_Transform(GLcontext context);
  76.  
  77. #ifndef __VBCC__ //replaced with macro
  78.     INLINE void v_ToScreen(GLcontext context, int i);
  79. #endif
  80.  
  81. extern void m_CombineMatrices(GLcontext context);
  82. extern void m_BuildInverted(GLcontext context);
  83.  
  84. extern void hc_ClipAndDrawLine(GLcontext context, MGLPolygon *poly, ULONG or_codes);
  85. extern void hc_ClipAndDrawPoly(GLcontext context, MGLPolygon *poly, ULONG or_codes);
  86.  
  87. extern void hc_ClipPoly(GLcontext context, MGLPolygon *poly, PolyBuffer *out, int clipstart, ULONG or_codes);
  88.  
  89. extern void hc_ClipPolyFF(GLcontext context, MGLPolygon *poly, ULONG or_codes);
  90.  
  91.  
  92. //this index is generated by clip function:
  93.  
  94. static PolyBuffer clip[MGL_MAXVERTS];
  95.  
  96.  
  97. //Surgeon: moved from GLVertex*f to after culling:
  98.  
  99. INLINE void PrepTexCoords(GLcontext context, int start, const int numverts, GLboolean cullfan)
  100. {
  101.    int i;
  102.    GLfloat umul, vmul;
  103.    MGLVertex *v;
  104.  
  105.    if(context->Texture2D_State[0] == GL_TRUE && context->w3dTexBuffer[context->CurrentBinding])
  106.    {
  107.     if (context->w3dChipID == W3D_CHIP_VIRGE)
  108.     {
  109.         umul = (float)(context->w3dTexBuffer[context->CurrentBinding]->texwidth-1);
  110.         vmul = (float)(context->w3dTexBuffer[context->CurrentBinding]->texheight-1);
  111.     }
  112.     else
  113.     {
  114.         umul = (float)(context->w3dTexBuffer[context->CurrentBinding]->texwidth);
  115.         vmul = (float)(context->w3dTexBuffer[context->CurrentBinding]->texheight);
  116.     }
  117.  
  118.     if(cullfan == GL_TRUE)
  119.     {
  120.         context->VertexBuffer[0].v.u *= umul;
  121.         context->VertexBuffer[0].v.v *= vmul;
  122.     }
  123.  
  124.     v = &(context->VertexBuffer[start]);
  125.     i = numverts;
  126.  
  127.     do
  128.     {
  129.         v->v.u *= umul;
  130.         v->v.v *= vmul;
  131.     v++;
  132.     } while (--i);
  133.    }
  134. }
  135.  
  136.  
  137.  
  138. #define CM_0 OF_11
  139. #define CM_1 OF_12
  140. #define CM_2 OF_13
  141. #define CM_3 OF_21
  142. #define CM_4 OF_22
  143. #define CM_5 OF_23
  144. #define CM_6 OF_31
  145. #define CM_7 OF_32
  146. #define CM_8 OF_33
  147.  
  148.  
  149. /*
  150. ** This computationally intensive piece of code generates coordinates
  151. ** for the reflective image used in spherical environment mapping.
  152. ** This is a good place for optimizations.
  153. ** After generation, transforms into the clipping space...
  154. **
  155. ** Note that this is after the book. It is probably a big time-eater.
  156. **
  157. ** (Turned out not to be so time intensive after all...)
  158. */
  159.  
  160.  
  161. void v_GenTexCoords(GLcontext context, int vertex)
  162. {
  163. #ifdef __M68K__
  164.     float u[4];
  165. #endif
  166.     float ul;
  167.     float nx,ny,nz;
  168.     float nu;
  169.     float rx,ry,rz;
  170.     float m;
  171.     float s,t;
  172.  
  173.     float a11,a12,a13,a14;
  174.     float a21,a22,a23,a24;
  175.     float a31,a32,a33,a34;
  176.     float a41,a42,a43,a44;
  177.  
  178.     float b11,b12,b13,b14;
  179.     float b21,b22,b23,b24;
  180.     float b31,b32,b33,b34;
  181.     float b41,b42,b43,b44;
  182.  
  183.     #define a(x)  (CurrentMV->v[OF_##x])
  184.     #define b(x)  (CurrentP->v[OF_##x])
  185.     #define verx  (context->VertexBuffer[vertex].bx)
  186.     #define very  (context->VertexBuffer[vertex].by)
  187.     #define verz  (context->VertexBuffer[vertex].bz)
  188.     #define verw  (context->VertexBuffer[vertex].bw)
  189.  
  190. #ifdef __PPC__
  191.  
  192.     a11 = a(11);    b11 = b(11);
  193.     a12 = a(12);    b12 = b(12);
  194.     a13 = a(13);    b13 = b(13);
  195.     a14 = a(14);    b14 = b(14);
  196.  
  197.     a21 = a(21);    b21 = b(21);
  198.     a22 = a(22);    b22 = b(22);
  199.     a23 = a(23);    b23 = b(23);
  200.     a24 = a(24);    b24 = b(24);
  201.  
  202.     a31 = a(31);    b31 = b(31);
  203.     a32 = a(32);    b32 = b(32);
  204.     a33 = a(33);    b33 = b(33);
  205.     a34 = a(34);    b34 = b(34);
  206.  
  207.     a41 = a(41);    b41 = b(41);
  208.     a42 = a(42);    b42 = b(42);
  209.     a43 = a(43);    b43 = b(43);
  210.     a44 = a(44);    b44 = b(44);
  211.  
  212.     #define A_0 a14
  213.     #define A_1 a24
  214.     #define A_2 a34
  215.     #define A_3 a44
  216.  
  217.     #define u(x) (A_##x)
  218.  
  219. #else
  220.  
  221.     a11 = a(11);    b11 = b(11);
  222.     a12 = a(12);    b12 = b(12);
  223.     a13 = a(13);    b13 = b(13);
  224.     u[0] = a(14);    b14 = b(14);
  225.  
  226.     a21 = a(21);    b21 = b(21);
  227.     a22 = a(22);    b22 = b(22);
  228.     a23 = a(23);    b23 = b(23);
  229.     u[1] = a(24);    b24 = b(24);
  230.  
  231.     a31 = a(31);    b31 = b(31);
  232.     a32 = a(32);    b32 = b(32);
  233.     a33 = a(33);    b33 = b(33);
  234.     u[2] = a(34);    b34 = b(34);
  235.  
  236.     a41 = a(41);    b41 = b(41);
  237.     a42 = a(42);    b42 = b(42);
  238.     a43 = a(43);    b43 = b(43);
  239.     u[3] = a(44);    b44 = b(44);
  240.  
  241.     #define u(x) (u[x])
  242.  
  243. #endif
  244.  
  245. //some common special-case optimizations by surgeon
  246.  
  247.     if(context->WOne_Hint == GL_FALSE)
  248.     {
  249.         if(!(CurrentMV->flags & MGLMASK_0001))
  250.         {
  251.         u(0) *= verw;
  252.         u(1) *= verw;
  253.         u(2) *= verw;
  254.         u(3) *= verw;
  255.  
  256.         u(0) += verz*a13;
  257.         u(1) += verz*a23;
  258.         u(2) += verz*a33;
  259.         u(3) += verz*a43;
  260.  
  261.         u(0) += very*a12;
  262.         u(1) += very*a22;
  263.         u(2) += very*a32;
  264.         u(3) += very*a42;
  265.  
  266.         u(0) += verx*a11;
  267.         u(1) += verx*a21;
  268.         u(2) += verx*a31;
  269.         u(3) += verx*a41;
  270.         }
  271.         else //special case
  272.         {
  273.         u(0) *= verw;
  274.         u(1) *= verw;
  275.         u(2) *= verw;
  276.         u(3) = verw;
  277.  
  278.         u(0) += verz*a13;
  279.         u(1) += verz*a23;
  280.         u(2) += verz*a33;
  281.  
  282.         u(0) += very*a12;
  283.         u(1) += very*a22;
  284.         u(2) += very*a32;
  285.  
  286.         u(0) += verx*a11;
  287.         u(1) += verx*a21;
  288.         u(2) += verx*a31;
  289.         }
  290.     }
  291.     else //special case
  292.     {
  293.         if(!(CurrentMV->flags & MGLMASK_0001))
  294.         {
  295.         u(0) += verz*a13;
  296.         u(1) += verz*a23;
  297.         u(2) += verz*a33;
  298.         u(3) += verz*a43;
  299.  
  300.         u(0) += very*a12;
  301.         u(1) += very*a22;
  302.         u(2) += very*a32;
  303.         u(3) += very*a42;
  304.  
  305.         u(0) += verx*a11;
  306.         u(1) += verx*a21;
  307.         u(2) += verx*a31;
  308.         u(3) += verx*a41;
  309.         }
  310.         else //special case
  311.         {
  312.         u(0) += verz*a13;
  313.         u(1) += verz*a23;
  314.         u(2) += verz*a33;
  315.  
  316.         u(0) += very*a12;
  317.         u(1) += very*a22;
  318.         u(2) += very*a32;
  319.  
  320.         u(0) += verx*a11;
  321.         u(1) += verx*a21;
  322.         u(2) += verx*a31;
  323.         }
  324.     }
  325.  
  326.     b14 *= u(3); 
  327.     b24 *= u(3); 
  328.     b34 *= u(3); 
  329.     b44 *= u(3); 
  330.  
  331.     b14 += u(2)*b13; 
  332.     b24 += u(2)*b23; 
  333.     b34 += u(2)*b33; 
  334.     b44 += u(2)*b43; 
  335.  
  336.     b14 += u(1)*b12; 
  337.     b24 += u(1)*b22; 
  338.     b34 += u(1)*b32; 
  339.     b44 += u(1)*b42; 
  340.  
  341.     b14 += u(0)*b11; 
  342.     b24 += u(0)*b21; 
  343.     b34 += u(0)*b31; 
  344.     b44 += u(0)*b41; 
  345.  
  346.     verx = b14;
  347.     very = b24;
  348.     verz = b34;
  349.     verw = b44;
  350.  
  351.  
  352.     #undef a
  353.     #undef b
  354.     #undef verx
  355.     #undef very
  356.     #undef verz
  357.     #undef verw
  358.  
  359.  
  360.     if(u(3) != 1.f)
  361.     {
  362.         u(3) = 1.0 / u(3);
  363.         u(0) *= u(3);
  364.         u(1) *= u(3);
  365.         u(2) *= u(3);
  366.     }
  367.  
  368.     ul = (float)sqrt((double)(u(0)*u(0)+u(1)*u(1)+u(2)*u(2)));
  369.  
  370.     if (ul == 0.f)
  371.         return;
  372.  
  373.     ul = 1.0 / ul;
  374.     u(0) *= ul;
  375.     u(1) *= ul;
  376.     u(2) *= ul;
  377.  
  378.     if(context->NormalBufferPointer > 0)
  379.     {
  380.     int nbp = context->VertexBuffer[vertex].normal;
  381.  
  382.     #define ver(c)  (context->NormalBuffer[nbp].c)
  383.     #define b(x)    (context->InvRot[x])
  384.  
  385.         // InvRot is row-major
  386.  
  387.         nx  = ver(x)*b(0);
  388.         ny  = ver(x)*b(1);
  389.         nz  = ver(x)*b(2);
  390.     
  391.         nx += ver(y)*b(3);
  392.         ny += ver(y)*b(4);
  393.         nz += ver(y)*b(5);
  394.  
  395.         nx += ver(z)*b(6);
  396.         ny += ver(z)*b(7);
  397.         nz += ver(z)*b(8);
  398.     
  399.     #undef b
  400.     #undef ver
  401.     }
  402.     else
  403.     {
  404.     #define ver(c)  (context->NormalBuffer[0].c)
  405.     #define b(x)    (context->InvRot[x])
  406.  
  407.         // InvRot is row-major
  408.  
  409.         nx  = ver(x)*b(0);
  410.         ny  = ver(x)*b(1);
  411.         nz  = ver(x)*b(2);
  412.     
  413.         nx += ver(y)*b(3);
  414.         ny += ver(y)*b(4);
  415.         nz += ver(y)*b(5);
  416.  
  417.         nx += ver(z)*b(6);
  418.         ny += ver(z)*b(7);
  419.         nz += ver(z)*b(8);
  420.     
  421.     #undef b
  422.     #undef ver
  423.     }
  424.  
  425.  
  426.     nu  = nx*u(0) + ny*u(1) + nz*u(2);
  427.     nu *= 2.f;
  428.  
  429.     rx = u(0) - nx*nu;
  430.     ry = u(1) - ny*nu;
  431.     rz = u(2) - nz*nu;
  432.  
  433.     rz += 1.f;    
  434.     m = 0.5f / (float)sqrt((double)(rx*rx + ry*ry + rz*rz));
  435.  
  436.  
  437.     if (context->TextureGenS_State == GL_TRUE)
  438.     {
  439.         s = rx*m + 0.5;
  440.         context->VertexBuffer[vertex].v.u = s;
  441.     }
  442.  
  443.     if (context->TextureGenT_State == GL_TRUE)
  444.     {
  445.         t = ry*m + 0.5;
  446.         context->VertexBuffer[vertex].v.v = t;
  447.     }
  448.  
  449. #undef u
  450. }
  451.  
  452.  
  453. INLINE GLvoid v_Transform(GLcontext context)
  454. {
  455. #if !defined(DISABLE_TRANSFORMATION)
  456.     int i;
  457.  
  458.    if (context->TextureGenS_State == GL_TRUE || context->TextureGenT_State == GL_TRUE)
  459.    {
  460. #ifndef INLINE_MATRIX_INVERSION
  461.     if (context->InvRotValid == GL_FALSE)
  462.         m_BuildInverted(context);
  463. #endif
  464.     for (i=0; i<context->VertexBufferPointer; i++)
  465.     {
  466.         v_GenTexCoords(context, i);
  467.     }
  468.    }
  469.  
  470.    else
  471.    {
  472.     if (context->CombinedValid == GL_FALSE)
  473.     {
  474.         m_CombineMatrices(context);
  475.     }
  476.  
  477.     if (context->WOne_Hint == GL_FALSE)
  478.     {
  479.         #define a(x) (context->CombinedMatrix.v[OF_##x])
  480.  
  481.         float a11 = a(11);
  482.         float a12 = a(12);
  483.         float a13 = a(13);
  484.         float a14 = a(14);
  485.         float a21 = a(21);
  486.         float a22 = a(22);
  487.         float a23 = a(23);
  488.         float a24 = a(24);
  489.         float a31 = a(31);
  490.         float a32 = a(32);
  491.         float a33 = a(33);
  492.         float a34 = a(34);
  493.         float a41 = a(41);
  494.         float a42 = a(42);
  495.         float a43 = a(43);
  496.         float a44 = a(44);
  497.  
  498.         MGLVertex *v = &context->VertexBuffer[0];
  499.  
  500.         i = context->VertexBufferPointer;
  501.         do
  502.         {
  503.         float x = v->bx;
  504.         float y = v->by;
  505.         float z = v->bz;
  506.         float w = v->bw;
  507.  
  508.         v->bx = a11*x + a12*y + a13*z + a14*w;
  509.         v->by = a21*x + a22*y + a23*z + a24*w;
  510.         v->bz = a31*x + a32*y + a33*z + a34*w;
  511.         v->bw = a41*x + a42*y + a43*z + a44*w;
  512.  
  513.         v++;
  514.         } while (--i);
  515.  
  516.         #undef a
  517.     }
  518.     else
  519.     {
  520.         #define a(x) (context->CombinedMatrix.v[OF_##x])
  521.  
  522.         float a11 = a(11);
  523.         float a12 = a(12);
  524.         float a13 = a(13);
  525.         float a14 = a(14);
  526.         float a21 = a(21);
  527.         float a22 = a(22);
  528.         float a23 = a(23);
  529.         float a24 = a(24);
  530.         float a31 = a(31);
  531.         float a32 = a(32);
  532.         float a33 = a(33);
  533.         float a34 = a(34);
  534.         float a41 = a(41);
  535.         float a42 = a(42);
  536.         float a43 = a(43);
  537.         float a44 = a(44);
  538.  
  539.         MGLVertex *v = &context->VertexBuffer[0];
  540.  
  541.         i = context->VertexBufferPointer;
  542.  
  543.         do
  544.         {
  545.         float x = v->bx;
  546.         float y = v->by;
  547.         float z = v->bz;
  548.  
  549.         v->bx = a11*x + a12*y + a13*z + a14;
  550.         v->by = a21*x + a22*y + a23*z + a24;
  551.         v->bz = a31*x + a32*y + a33*z + a34;
  552.         v->bw = a41*x + a42*y + a43*z + a44;
  553.  
  554.         v++;
  555.         } while (--i);
  556.  
  557.     #undef a
  558.     }
  559.   }
  560. #else
  561. // Does nothing
  562. #endif
  563. }
  564.  
  565.  
  566. #ifdef __VBCC__
  567.  
  568. //VBCC only does inlining on highest optimization level :-/
  569.  
  570. #define v_ToScreen(ctx,vnum){\
  571. static float wdiv;\
  572. wdiv = 1.0 / ctx->VertexBuffer[vnum].bw; \
  573. ctx->VertexBuffer[vnum].v.x = ctx->ax + ctx->VertexBuffer[vnum].bx * wdiv * ctx->sx; \
  574. ctx->VertexBuffer[vnum].v.y = ctx->ay - ctx->VertexBuffer[vnum].by * wdiv * ctx->sy; \
  575. ctx->VertexBuffer[vnum].v.z = ctx->az + ctx->VertexBuffer[vnum].bz * wdiv * ctx->sz; \
  576. if (ctx->ZOffset_State == GL_TRUE) ctx->VertexBuffer[vnum].v.z += (W3D_Float)ctx->ZOffset; \
  577. if (context->CurrentTexQValid == GL_FALSE) ctx->VertexBuffer[vnum].v.w = wdiv; \
  578. else ctx->VertexBuffer[vnum].v.w = ctx->VertexBuffer[vnum].q;}\
  579.  
  580. #define v_ToScreenVA(ctx,vnum){\
  581. static float wdiv;\
  582. wdiv = 1.0 / ctx->VertexBuffer[vnum].bw; \
  583. ctx->VertexBuffer[vnum].bx = ctx->ax + ctx->VertexBuffer[vnum].bx * wdiv * ctx->sx; \
  584. ctx->VertexBuffer[vnum].by = ctx->ay - ctx->VertexBuffer[vnum].by * wdiv * ctx->sy; \
  585. ctx->VertexBuffer[vnum].bz = ctx->az + ctx->VertexBuffer[vnum].bz * wdiv * ctx->sz; \
  586. if (ctx->ZOffset_State == GL_TRUE) ctx->VertexBuffer[vnum].bz += (W3D_Float)ctx->ZOffset; \
  587. if (context->CurrentTexQValid == GL_FALSE) ctx->VertexBuffer[vnum].v.w = wdiv; \
  588. else ctx->VertexBuffer[vnum].v.w = ctx->VertexBuffer[vnum].q;}\
  589.  
  590. #else
  591.  
  592. INLINE void v_ToScreen(GLcontext context, int i)
  593. {
  594. #if !defined(DISABLE_TRANSFORMATION)
  595.  
  596.     float w;
  597.     w = 1.0 / context->VertexBuffer[i].bw;
  598.  
  599.     context->VertexBuffer[i].v.x = context->ax + context->VertexBuffer[i].bx * w * context->sx;
  600.     context->VertexBuffer[i].v.y = context->ay - context->VertexBuffer[i].by * w * context->sy;
  601.     context->VertexBuffer[i].v.z = context->az + context->VertexBuffer[i].bz * w * context->sz;
  602.  
  603.     if (context->ZOffset_State == GL_TRUE)
  604.         context->VertexBuffer[i].v.z += (W3D_Float)context->ZOffset;
  605.  
  606.     if (context->CurrentTexQValid == GL_FALSE)
  607.         context->VertexBuffer[i].v.w = w;
  608.     else
  609.         context->VertexBuffer[i].v.w = context->VertexBuffer[i].q;
  610.  
  611. #else
  612.     context->VertexBuffer[i].v.x = context->VertexBuffer[i].bx;
  613.     context->VertexBuffer[i].v.y = context->VertexBuffer[i].by;
  614.     context->VertexBuffer[i].v.z = 1.0 - context->VertexBuffer[i].bz;
  615.     context->VertexBuffer[i].v.w = context->VertexBuffer[i].q;
  616. #endif
  617. }
  618.  
  619. INLINE void v_ToScreenVA(GLcontext context, int i)
  620. {
  621.     float w;
  622.     w = 1.0 / context->VertexBuffer[i].bw;
  623.  
  624.     context->VertexBuffer[i].bx = context->ax + context->VertexBuffer[i].bx * w * context->sx;
  625.     context->VertexBuffer[i].by = context->ay - context->VertexBuffer[i].by * w * context->sy;
  626.     context->VertexBuffer[i].bz = context->az + context->VertexBuffer[i].bz * w * context->sz;
  627.  
  628.     if (context->ZOffset_State == GL_TRUE)
  629.         context->VertexBuffer[i].bz += (W3D_Float)context->ZOffset;
  630.  
  631.     if (context->CurrentTexQValid == GL_FALSE)
  632.         context->VertexBuffer[i].v.w = w;
  633.     else
  634.         context->VertexBuffer[i].v.w = context->VertexBuffer[i].q;
  635. }
  636.  
  637.  
  638. #endif
  639.  
  640.  
  641. /*
  642. ** Multitexturing:
  643. ** See mglDrawMultitexBuffer
  644. */
  645.  
  646. #define ENABLE_BLEND {if(mini_CurrentContext->Blend_State == GL_FALSE) W3D_SetState(context->w3dContext, W3D_BLENDING, W3D_ENABLE);}
  647.  
  648. #define DISABLE_BLEND {if(mini_CurrentContext->Blend_State == GL_FALSE) W3D_SetState(context->w3dContext, W3D_BLENDING, W3D_DISABLE);}
  649.  
  650.  
  651.  
  652. #if 0 //should go to same buffer as GL_POLYGON
  653.  
  654. static void Multitex_PolyBuffer(GLcontext context, W3D_Vertex **verts, int numpolys, GLboolean typecheck)
  655. {
  656.     int i,j;
  657.     int first;
  658.     ULONG error;
  659.     static W3D_TrianglesV tris;
  660.  
  661.  
  662.     ENABLE_BLEND
  663.  
  664.     tris.tex = context->w3dTexBuffer[context->VirtualBinding];
  665.     tris.st_pattern = NULL;
  666.  
  667.     i = 0;
  668.     first = 0;
  669.  
  670.     do
  671.     {
  672.        PolyBuffer *p = &clip[i];
  673.  
  674.     float w = context->w3dTexBuffer[context->VirtualBinding]->texwidth;
  675.     float h = context->w3dTexBuffer[context->VirtualBinding]->texheight;
  676.  
  677.  
  678.         for(j=0; j<p->numverts; j++)
  679.         {
  680.     MGLVertex *v = &context->VertexBuffer[p->verts[j]];
  681.  
  682.     v->v.u = v->tcoord.s * w;
  683.     v->v.v = v->tcoord.t * h;
  684.  
  685.         }
  686.  
  687.     tris.v = &verts[first];
  688.     tris.vertexcount = p->numverts;
  689.     first += p->numverts;
  690.  
  691.        if(typecheck && p->type == W3D_PRIMITIVE_TRISTRIP)
  692.        { 
  693.           error = W3D_DrawTriStripV(context->w3dContext, &tris);
  694.        }
  695.        else
  696.        {
  697.           error = W3D_DrawTriFanV(context->w3dContext, &tris);
  698.        }
  699.  
  700.     i++;
  701.     } while (i<numpolys);
  702.  
  703.     DISABLE_BLEND
  704. }
  705.  
  706. #endif
  707.  
  708.  
  709. //Surgeon: from hclip.c - hc_CodePoint is inlined manually
  710.  
  711. #define CLIP_EPS (1e-7)
  712.  
  713.  
  714. //primitive point emulation by Surgeon - works on voodoo3
  715.  
  716. void d_DrawPoints(GLcontext context)
  717. {
  718. #if !defined(DISABLE_TRANSFORMATION)
  719.     int i,j;
  720.     W3D_Triangle tri;
  721.     MGLVertex *vf;
  722.     ULONG error;
  723.  
  724.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  725.     return;
  726.  
  727.     v_Transform(context);
  728.  
  729.  
  730.     vf = context->VertexBuffer;
  731.  
  732.     for (i=0; i<context->VertexBufferPointer; i++)
  733.     {
  734.         MGLVertex *v = &vf[i];
  735.         float w = v->bw;
  736.  
  737.         if (w < CLIP_EPS )
  738.         {
  739.             continue;
  740.         }
  741.  
  742.         if (-w > v->bx)
  743.         {
  744.             continue;
  745.         }
  746.         else if (v->bx > w)
  747.         {
  748.             continue;
  749.         }
  750.  
  751.         if (-w > v->by)
  752.         {
  753.             continue;
  754.         }
  755.         else if (v->by > w)
  756.         {
  757.             continue;
  758.         }
  759.     
  760.         if (-w > v->bz)
  761.         {
  762.             continue;
  763.         }
  764.         else if (v->bz > w)
  765.         {
  766.             continue;
  767.         }
  768.  
  769.  
  770.         v_ToScreen(context, i);
  771.  
  772.         tri.v1 = context->VertexBuffer[i].v;
  773.         tri.v2 = context->VertexBuffer[i].v;
  774.         tri.v3 = context->VertexBuffer[i].v;
  775.         tri.v2.y += context->CurrentPointSize;
  776.         tri.v3.x += context->CurrentPointSize;
  777.         tri.tex = NULL;
  778.         tri.st_pattern = NULL;
  779.  
  780.         error = W3D_DrawTriangle(context->w3dContext, &tri);
  781.     }
  782. #else
  783.     int i;
  784.     W3D_Point p;
  785.     ULONG error;
  786.  
  787.     for (i=0;i<context->VertexBufferPointer; i++)
  788.     {
  789.     v_ToScreen(context,i);
  790.     p.v1 = (context->VertexBuffer[i].v);
  791.     p.tex = NULL;
  792.     p.pointsize = 1; //diameter
  793.     error = W3D_DrawPoint(context->w3dContext, &p);
  794.     }
  795. #endif
  796. }
  797.  
  798. void d_DrawLines(GLcontext context)
  799. {
  800. #if !defined(DISABLE_TRANSFORMATION)
  801.     int i,j;
  802.     W3D_Line lin;
  803.     ULONG or_code, and_code;
  804.     ULONG error;
  805.  
  806.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  807.     return;
  808.  
  809.     v_Transform(context);
  810.  
  811.     for (i=0; i<context->VertexBufferPointer; i+=2)
  812.     {
  813.        for (j=i; j<i+2;j++)
  814.        {
  815.         MGLVertex *v = &(context->VertexBuffer[j]);
  816.         float w = v->bw;
  817.         ULONG outcode = 0;
  818.  
  819.         if (w < CLIP_EPS )
  820.         {
  821.             outcode |= MGL_CLIP_NEGW;
  822.         }
  823.  
  824.         if (-w > v->bx)
  825.         {
  826.             outcode |= MGL_CLIP_LEFT;
  827.         }
  828.         else if (v->bx > w)
  829.         {
  830.             outcode |= MGL_CLIP_RIGHT;
  831.         }
  832.  
  833.         if (-w > v->by)
  834.         {
  835.             outcode |= MGL_CLIP_BOTTOM;
  836.         }
  837.         else if (v->by > w)
  838.         {
  839.             outcode |= MGL_CLIP_TOP;
  840.         }
  841.     
  842.         if (-w > v->bz)
  843.         {
  844.             outcode |= MGL_CLIP_BACK;
  845.         }
  846.         else if (v->bz > w)
  847.         {
  848.             outcode |= MGL_CLIP_FRONT;
  849.         }
  850.  
  851.         v->outcode = outcode;
  852.         and_code &= outcode;
  853.         or_code  |= outcode;
  854.       }
  855.  
  856.     or_code = context->VertexBuffer[i+0].outcode
  857.         | context->VertexBuffer[i+1].outcode;
  858.  
  859.     and_code = context->VertexBuffer[i+0].outcode
  860.          & context->VertexBuffer[i+1].outcode;
  861.  
  862.     if (and_code) continue;
  863.  
  864.     PrepTexCoords(context, i, 2, GL_FALSE);
  865.  
  866.     if (or_code == 0)
  867.     {
  868.  
  869.         v_ToScreen(context, i);
  870.         v_ToScreen(context, i+1);
  871.         lin.v1 = (context->VertexBuffer[i+0].v);
  872.         lin.v2 = (context->VertexBuffer[i+1].v);
  873.         lin.tex = context->w3dTexBuffer[context->CurrentBinding];
  874.         lin.st_pattern = 0;
  875.         lin.st_enable = 0;
  876.         lin.st_factor = 1;
  877.         error = W3D_DrawLine(context->w3dContext, &lin);
  878. //            if (error != W3D_SUCCESS) kprintf("W3D_DrawTriangle = %ld\n",error);
  879.     }
  880.     else
  881.     {
  882.         static MGLPolygon poly;
  883.         poly.numverts = 2;
  884.         poly.verts[0] = i;
  885.         poly.verts[1] = i+1;
  886.         hc_ClipAndDrawLine(context, &poly, or_code);
  887.     }
  888.     }
  889. #else
  890.     int i;
  891.     W3D_Line lin;
  892.     ULONG error;
  893.  
  894.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  895.  
  896.     for (i=0;i<context->VertexBufferPointer; i+=2)
  897.     {
  898.     v_ToScreen(context,i);
  899.     v_ToScreen(context,i+1);
  900.     lin.v1 = (context->VertexBuffer[i+0].v);
  901.     lin.v2 = (context->VertexBuffer[i+1].v);
  902.     lin.tex = context->w3dTexBuffer[context->CurrentBinding];
  903.     lin.st_pattern = 0;
  904.     lin.st_enable = 0;
  905.     lin.st_factor = 1;
  906.     error = W3D_DrawLine(context->w3dContext, &lin);
  907. //        if (error != W3D_SUCCESS) kprintf("W3D_DrawTriangle = %ld\n", error);
  908.     }
  909. #endif
  910. }
  911.  
  912. void dh_DrawLine(GLcontext context, MGLPolygon *poly)
  913. {
  914.     ULONG error;
  915.     static W3D_Line lin;
  916.  
  917.     v_ToScreen(context, poly->verts[0]);
  918.     lin.v1 = (context->VertexBuffer[poly->verts[0]].v);
  919.     v_ToScreen(context, poly->verts[1]);
  920.     lin.v2 = (context->VertexBuffer[poly->verts[1]].v);
  921.  
  922.     lin.tex = context->w3dTexBuffer[context->CurrentBinding];
  923.     lin.st_pattern = 0;
  924.     lin.st_enable = 0;
  925.     lin.st_factor  = 1;
  926.     #ifndef NODRAW
  927.     error = W3D_DrawLine(context->w3dContext, &lin);
  928. //    if (error != W3D_SUCCESS) kprintf("W3D_DrawTriFan = %ld\n", error);
  929.     #endif
  930. }
  931.  
  932. void d_DrawLineStrip(GLcontext context)
  933. {
  934. }
  935.  
  936. //surgeon: added fast path when primitive or_code equals 0
  937. //surgeon: added buffering for clipping events
  938. //multitexturing not finished yet
  939.  
  940. void d_DrawTriangleFan(GLcontext context)
  941. {
  942. #if !defined(DISABLE_TRANSFORMATION)
  943.     int i,j;
  944.     ULONG and_code, or_code;
  945.     ULONG local_or, local_and, guard_band;
  946.     ULONG error;
  947.     static W3D_Vertex **verts = NULL;
  948.     static GLboolean visible[MGL_MAXVERTS]; // Should be enough...?
  949.     static ULONG   complete[MGL_MAXVERTS];  // Ditto
  950.     static W3D_TrianglesV fan;
  951.     int triangle;
  952.     int pnum, free, backface, first, size;
  953.  
  954.     if (verts == NULL)
  955.     {
  956.         verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  957.         if (!verts) return;
  958.  
  959.     }
  960.  
  961.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  962.     return;
  963.  
  964.     v_Transform(context);
  965.  
  966.     and_code = 0xff; or_code = 0;
  967.  
  968.     for (i=0; i<context->VertexBufferPointer; i++)
  969.     {
  970.         MGLVertex *v = &(context->VertexBuffer[i]);
  971.         float w = v->bw;
  972.         ULONG outcode = 0;
  973.  
  974.         if (w < CLIP_EPS )
  975.         {
  976.             outcode |= MGL_CLIP_NEGW;
  977.         }
  978.  
  979.         if (-w > v->bx)
  980.         {
  981.             outcode |= MGL_CLIP_LEFT;
  982.         }
  983.         else if (v->bx > w)
  984.         {
  985.             outcode |= MGL_CLIP_RIGHT;
  986.         }
  987.  
  988.         if (-w > v->by)
  989.         {
  990.             outcode |= MGL_CLIP_BOTTOM;
  991.         }
  992.         else if (v->by > w)
  993.         {
  994.             outcode |= MGL_CLIP_TOP;
  995.         }
  996.     
  997.         if (-w > v->bz)
  998.         {
  999.             outcode |= MGL_CLIP_BACK;
  1000.         }
  1001.         else if (v->bz > w)
  1002.         {
  1003.             outcode |= MGL_CLIP_FRONT;
  1004.         }
  1005.  
  1006.         v->outcode = outcode;
  1007.         and_code &= outcode;
  1008.         or_code |= outcode;
  1009.  
  1010.     }
  1011.  
  1012.    if (and_code)
  1013.    {
  1014.     return;
  1015.    }
  1016.    else if(or_code == 0 || (or_code & context->ClipFlags))
  1017.    {
  1018.     guard_band = or_code;
  1019.    }
  1020.    else
  1021.    {
  1022.     float gcw;
  1023.     ULONG guard_code;
  1024.     MGLVertex *v = &context->VertexBuffer[0];
  1025.  
  1026.     i = context->VertexBufferPointer;
  1027.     guard_band = 0;
  1028.  
  1029.     do
  1030.     {
  1031.        if(v->outcode)
  1032.        {
  1033.         gcw = v->bw * 2.0;
  1034.         guard_code = 0;
  1035.  
  1036.         if (-gcw > v->bx)
  1037.             guard_code |= MGL_CLIP_LEFT;
  1038.         else if (v->bx > gcw)
  1039.             guard_code |= MGL_CLIP_RIGHT;
  1040.  
  1041.         if (-gcw > v->by)
  1042.             guard_code |= MGL_CLIP_BOTTOM;
  1043.         else if (v->by > gcw)
  1044.             guard_code |= MGL_CLIP_TOP;
  1045.  
  1046.         guard_band |= guard_code;
  1047.        }
  1048.  
  1049.     v++;
  1050.     } while (--i && guard_band == 0);
  1051.    }
  1052.  
  1053.    if (guard_band == 0) //trifan completely visible
  1054.    {
  1055.        first = 0;
  1056.        size = context->VertexBufferPointer;
  1057.  
  1058.        v_ToScreen(context, 0);
  1059.        v_ToScreen(context, 1);
  1060.        v_ToScreen(context, 2);
  1061.  
  1062.        i = 3;
  1063.        while (i < context->VertexBufferPointer)
  1064.        {
  1065.         v_ToScreen(context, i);
  1066.        i++;
  1067.        }
  1068.  
  1069.        if(context->CullFace_State == GL_TRUE)
  1070.        {
  1071.            float area;
  1072.         float sign;
  1073.         float x0,y0;
  1074.         float x1,y1;
  1075.         float x2,y2;
  1076.  
  1077.         sign = (float)(-context->CurrentCullSign);
  1078.  
  1079.            #define x(i) (context->VertexBuffer[i].v.x)
  1080.            #define y(i) (context->VertexBuffer[i].v.y)
  1081.  
  1082.            backface = 0;
  1083.  
  1084.         if(size == 3)
  1085.         {
  1086.            x1 = x(1) - x(0);
  1087.            y1 = y(1) - y(0);
  1088.            x2 = x(2) - x(0);
  1089.            y2 = y(2) - y(0);
  1090.        
  1091.            area = y2*x1 - x2*y1;
  1092.            area *= sign;
  1093.         }
  1094.         else
  1095.         {
  1096.            x0 = x(0);
  1097.            y0 = y(0);
  1098.            x1 = x(1) - x0;
  1099.            y1 = y(1) - y0;
  1100.            x2 = x(2) - x0;
  1101.            y2 = y(2) - y0;
  1102.  
  1103.            area = y2*x1 - x2*y1;
  1104.            area *= sign;
  1105.  
  1106.            if(area < 0.f)
  1107.            {
  1108.             first++;
  1109.             area = 0.f;
  1110.            }
  1111.  
  1112.            i = 1;
  1113.            do
  1114.            {
  1115.            float area2;
  1116.  
  1117.            x1 = x2;
  1118.            y1 = y2;
  1119.            x2 = x(i+2) - x0;
  1120.            y2 = y(i+2) - y0;
  1121.  
  1122.            area2 = y2*x1 - x2*y1;
  1123.            area2 *= sign;
  1124.  
  1125.              if(area2 < 0.f)
  1126.              {
  1127.             if(first == i)    first++;
  1128.             else        backface++;
  1129.              }
  1130.              else
  1131.              {
  1132.             backface = 0;
  1133.             area += area2;
  1134.              }
  1135.            i++;
  1136.            } while (i < size-2);
  1137.         size -= backface+first;
  1138.         }
  1139.  
  1140.        if (area < context->MinTriArea)
  1141.        return;
  1142.        }
  1143.     #undef x
  1144.     #undef y
  1145.  
  1146.     verts[0] = &(context->VertexBuffer[0].v);
  1147.  
  1148.     i = 1;
  1149.  
  1150.     do
  1151.     {
  1152.        verts[i] = &(context->VertexBuffer[i+first].v);
  1153.        i++;
  1154.     } while (i < size);
  1155.  
  1156.     PrepTexCoords(context, first+1, size-1, GL_TRUE);
  1157.  
  1158.     fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  1159.     fan.vertexcount = size;
  1160.     fan.st_pattern = NULL;
  1161.     fan.v = &verts[0];
  1162.  
  1163.     W3D_DrawTriFanV(context->w3dContext, &fan);
  1164.  
  1165.    return;
  1166.    }
  1167.  
  1168.     /*
  1169.     ** Up to now everything is like a polygon. Unlike a polygon, however,
  1170.     ** triangle fans and strips may be concave, and each individual triangle
  1171.     ** might be backfacing.
  1172.     **
  1173.     ** We calculate how many of the triangles are visible.
  1174.     */
  1175.  
  1176.     backface = 0;
  1177.  
  1178.    if(context->CullFace_State == GL_FALSE)
  1179.    {
  1180.     for (i=1,triangle=0; i<context->VertexBufferPointer - 1; i++, triangle++)
  1181.     {
  1182.         local_or = context->VertexBuffer[0].outcode
  1183.             | context->VertexBuffer[i].outcode
  1184.             | context->VertexBuffer[i+1].outcode;
  1185.  
  1186.         local_and = context->VertexBuffer[0].outcode
  1187.             & context->VertexBuffer[i].outcode
  1188.             & context->VertexBuffer[i+1].outcode;
  1189.  
  1190.  
  1191.         if (local_and == 0) // if the local and code is zero, we're not
  1192.         {                   // completely off screen.
  1193. // if our local or codes are zero, we are completely visible
  1194.  
  1195.             complete[triangle] = local_or;
  1196.             visible[triangle] = GL_TRUE;
  1197.             backface = 0;
  1198.         }
  1199.         else
  1200.         {
  1201.             visible[triangle] = GL_FALSE;
  1202.             backface++;
  1203.         }
  1204.     }
  1205.    }
  1206.    else
  1207.    {
  1208.     for (i=1,triangle=0; i<context->VertexBufferPointer - 1; i++, triangle++)
  1209.     {
  1210.         local_or = context->VertexBuffer[0].outcode
  1211.             | context->VertexBuffer[i].outcode
  1212.             | context->VertexBuffer[i+1].outcode;
  1213.  
  1214.         local_and = context->VertexBuffer[0].outcode
  1215.             & context->VertexBuffer[i].outcode
  1216.             & context->VertexBuffer[i+1].outcode;
  1217.  
  1218.  
  1219.         if (local_and == 0) // if the local and code is zero, we're not
  1220.         {                   // completely off screen.
  1221. // if our local or codes are zero, we are completely visible
  1222.  
  1223.             complete[triangle] = local_or;
  1224.  
  1225.             if (local_or & MGL_CLIP_NEGW)
  1226.             {
  1227.                 visible[triangle] = GL_TRUE;
  1228.                 backface = 0;
  1229.             }
  1230.             else
  1231.             {
  1232.                 visible[triangle] = hc_DecideFrontface(context, &(context->VertexBuffer[0]), &(context->VertexBuffer[i]), &(context->VertexBuffer[i+1]));
  1233.  
  1234.                 if(visible[triangle] == GL_FALSE)
  1235.                     backface++;
  1236.                 else
  1237.                     backface = 0;
  1238.             }
  1239.         }
  1240.         else
  1241.         {
  1242.             visible[triangle] = GL_FALSE;
  1243.             backface++;
  1244.         }
  1245.     }
  1246.    }
  1247.  
  1248. //early out:
  1249.     if(triangle == backface)
  1250.     return;
  1251.  
  1252.     context->VertexBufferPointer -= backface; //surgeon 260302
  1253.  
  1254.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  1255.  
  1256.     /*
  1257.     ** Draw...
  1258.     ** There are three cases:
  1259.     **
  1260.     ** 1) Triangle is partially visible
  1261.     ** 2) Triangle is fully visible
  1262.     ** 3) Triangle is invisible
  1263.     **
  1264.     ** In case 1, we draw the triangle with clip_ClipAndDrawPoly.
  1265.     ** In case 2, we collect a triangle fan/strip of maximum length
  1266.     ** and draw that directly
  1267.     ** in case 3... WE IGNORE IT! HA!
  1268.     */
  1269.  
  1270.     free = context->VertexBufferPointer;
  1271.     pnum = 0;
  1272.  
  1273.     triangle = 0; i=1;
  1274.     do
  1275.     {
  1276.         if (visible[triangle] == GL_FALSE) // case 3
  1277.         {
  1278.             triangle ++;
  1279.             i        ++;
  1280.         }
  1281.         else
  1282.         {
  1283.             if (complete[triangle]) // case 1
  1284.             {
  1285.                 static MGLPolygon poly;
  1286.                 poly.numverts = 3;
  1287.                 poly.verts[0] = 0;
  1288.                 poly.verts[1] = i;
  1289.                 poly.verts[2] = i + 1;
  1290.  
  1291.                 hc_ClipPoly(context, &poly, &clip[pnum], free, complete[triangle]);
  1292.                 triangle++; i++;
  1293.  
  1294.                 if(clip[pnum].numverts)
  1295.                 {
  1296.                 free = clip[pnum].nextfree;
  1297.                 pnum++;
  1298.                 }
  1299.             }
  1300.             else
  1301.             {   // case 2 (the difficult part)
  1302.                 int k=3;
  1303.                 clip[pnum].verts[0] = 0;
  1304.                 clip[pnum].verts[1] = i;
  1305.                 clip[pnum].verts[2] = i+1;
  1306.  
  1307.                 triangle ++;
  1308.                 i        ++;
  1309.  
  1310.                 while (complete[triangle]==0 && visible[triangle] && i<context->VertexBufferPointer - 1)
  1311.                 {
  1312.                 clip[pnum].verts[k] = i+1;
  1313.  
  1314.                 i++; k++; triangle++;
  1315.                 }
  1316.             clip[pnum].numverts = k;
  1317.             pnum++;
  1318.             }
  1319.         }
  1320.     } while (i<context->VertexBufferPointer-1);
  1321.  
  1322.  
  1323. //Project to screen and draw:
  1324.  
  1325.     visible[context->VertexBufferPointer-2] = GL_FALSE;
  1326.     visible[context->VertexBufferPointer-1] = GL_FALSE;
  1327.  
  1328.    //project clipverts
  1329.  
  1330.    for(i=context->VertexBufferPointer; i<free; i++)
  1331.    {
  1332.     v_ToScreen(context, i);
  1333.    }
  1334.  
  1335.    fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  1336.    fan.st_pattern = NULL;
  1337.  
  1338.      j = 0, first = 0;
  1339.      do
  1340.      {
  1341.       PolyBuffer *p = &clip[j];
  1342.  
  1343.       for (i=0; i<p->numverts; i++)
  1344.       {
  1345.         int vert = p->verts[i];
  1346.  
  1347.         if(vert < context->VertexBufferPointer && visible[vert] < 2 /*== GL_FALSE*/)
  1348.         {
  1349.            visible[vert] = 2/*GL_TRUE*/;
  1350.            v_ToScreen(context, vert);
  1351.         }
  1352.  
  1353.       verts[i+first] = &(context->VertexBuffer[vert].v);
  1354.       }
  1355.  
  1356.     fan.vertexcount = p->numverts;
  1357.     fan.v = &verts[first];
  1358.     first += p->numverts;
  1359.  
  1360.     error = W3D_DrawTriFanV(context->w3dContext, &fan);
  1361.  
  1362.     j++;
  1363.       } while (j < pnum);
  1364.  
  1365. #if 0
  1366.    if(context->Texture2D_State[1])
  1367.     Multitex_PolyBuffer(context, verts, pnum, GL_FALSE);
  1368. #endif
  1369.  
  1370. #else
  1371.     int i;
  1372.     ULONG error;
  1373.     static W3D_Vertex *verts[MGL_MAXVERTS];
  1374.     static W3D_TrianglesV tris;
  1375.  
  1376.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  1377.  
  1378.     for (i=0; i<context->VertexBufferPointer; i++)
  1379.     {
  1380.         v_ToScreen(context, i);
  1381.         verts[i] = &(context->VertexBuffer[i].v);
  1382.     }
  1383.  
  1384.     tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  1385.     tris.st_pattern = NULL;
  1386.     tris.vertexcount = context->VertexBufferPointer;
  1387.     tris.v = verts;
  1388.  
  1389.     #ifndef NODRAW
  1390.     error = W3D_DrawTriFanV(context->w3dContext, &tris);
  1391.     #endif
  1392. #endif
  1393. }
  1394.  
  1395. //surgeon: added fast path when primitive or_code equals 0
  1396. //surgeon: added buffering for clipping events
  1397. //multitexturing not finished yet
  1398.  
  1399. void d_DrawTriangleStrip(GLcontext context)
  1400. {
  1401. #if !defined(DISABLE_TRANSFORMATION)
  1402.     int i,j;
  1403.     ULONG and_code, or_code, guard_band;
  1404.     ULONG local_or, local_and;
  1405.     ULONG error;
  1406.     static W3D_Vertex **verts = NULL;
  1407.     static GLboolean visible[MGL_MAXVERTS];     // Should be enough...?
  1408.     static ULONG   complete[MGL_MAXVERTS];    // Ditto
  1409.     static W3D_TrianglesV tris;
  1410.     int triangle = 0;
  1411. /*
  1412.     GLenum CurrentFrontFace = context->CurrentFrontFace;
  1413. */
  1414.     GLint CurrentCullSign = context->CurrentCullSign;
  1415.     int pnum, free, backface, first, size;
  1416.  
  1417.  
  1418.     if (verts == NULL)
  1419.     {
  1420.         verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  1421.         if (!verts) return;
  1422.  
  1423.     }
  1424.  
  1425.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  1426.     return;
  1427.  
  1428.     v_Transform(context);
  1429.  
  1430.     and_code = 0xff;
  1431.     or_code = 0;
  1432.  
  1433.     for (i=0; i<context->VertexBufferPointer; i++)
  1434.     {
  1435.         MGLVertex *v = &(context->VertexBuffer[i]);
  1436.         float w = v->bw;
  1437.         ULONG outcode = 0;
  1438.  
  1439.         if (w < CLIP_EPS )
  1440.         {
  1441.             outcode |= MGL_CLIP_NEGW;
  1442.         }
  1443.  
  1444.         if (-w > v->bx)
  1445.         {
  1446.             outcode |= MGL_CLIP_LEFT;
  1447.         }
  1448.         else if (v->bx > w)
  1449.         {
  1450.             outcode |= MGL_CLIP_RIGHT;
  1451.         }
  1452.  
  1453.         if (-w > v->by)
  1454.         {
  1455.             outcode |= MGL_CLIP_BOTTOM;
  1456.         }
  1457.         else if (v->by > w)
  1458.         {
  1459.             outcode |= MGL_CLIP_TOP;
  1460.         }
  1461.     
  1462.         if (-w > v->bz)
  1463.         {
  1464.             outcode |= MGL_CLIP_BACK;
  1465.         }
  1466.         else if (v->bz > w)
  1467.         {
  1468.             outcode |= MGL_CLIP_FRONT;
  1469.         }
  1470.  
  1471.         v->outcode = outcode;
  1472.         and_code &= outcode;
  1473.         or_code  |= outcode;
  1474.  
  1475.     }
  1476.  
  1477.    if (and_code)
  1478.         return;
  1479.  
  1480.    else if(or_code == 0 || (or_code & context->ClipFlags))
  1481.    {
  1482.     guard_band = or_code;
  1483.    }
  1484.    else
  1485.    {
  1486.     float gcw;
  1487.     ULONG guard_code;
  1488.     MGLVertex *v = &context->VertexBuffer[0];
  1489.  
  1490.     i = context->VertexBufferPointer;
  1491.     guard_band = 0;
  1492.  
  1493.     do
  1494.     {
  1495.        if(v->outcode)
  1496.        {
  1497.         gcw = v->bw * 2.0;
  1498.         guard_code = 0;
  1499.  
  1500.         if (-gcw > v->bx)
  1501.             guard_code |= MGL_CLIP_LEFT;
  1502.         else if (v->bx > gcw)
  1503.             guard_code |= MGL_CLIP_RIGHT;
  1504.  
  1505.         if (-gcw > v->by)
  1506.             guard_code |= MGL_CLIP_BOTTOM;
  1507.         else if (v->by > gcw)
  1508.             guard_code |= MGL_CLIP_TOP;
  1509.  
  1510.         guard_band |= guard_code;
  1511.        }
  1512.  
  1513.     v++;
  1514.     } while (--i && guard_band == 0);
  1515.    }
  1516.  
  1517.    if (guard_band == 0) //tristrip completely visible
  1518.    {
  1519.     first = 0;
  1520.     size = context->VertexBufferPointer;
  1521.  
  1522.        v_ToScreen(context, 0);
  1523.        v_ToScreen(context, 1);
  1524.        v_ToScreen(context, 2);
  1525.  
  1526.        i = 3;
  1527.        while (i < context->VertexBufferPointer)
  1528.        {
  1529.         v_ToScreen(context, i);
  1530.        i++;
  1531.        }
  1532.  
  1533.        if(context->CullFace_State == GL_TRUE)
  1534.        {
  1535.         float x1,y1;
  1536.         float x2,y2;
  1537.         float area;
  1538.         float sign;
  1539.  
  1540.         sign = (float)(-context->CurrentCullSign);
  1541.  
  1542.         #define x(i) (context->VertexBuffer[i].v.x)
  1543.         #define y(i) (context->VertexBuffer[i].v.y)
  1544.  
  1545.         backface = 0;
  1546.  
  1547.         if(size == 3)
  1548.         {
  1549.            x1 = x(1) - x(0);
  1550.            y1 = y(1) - y(0);
  1551.            x2 = x(2) - x(0);
  1552.            y2 = y(2) - y(0);
  1553.        
  1554.            area = y2*x1 - x2*y1;
  1555.            area *= sign;
  1556.         }
  1557.         else
  1558.         {
  1559.         float a1 = x(1);
  1560.         float b1 = y(1);
  1561.         float a2 = x(2);
  1562.         float b2 = y(2);
  1563.  
  1564.         x1 = a1 - x(0);
  1565.         y1 = b1 - y(0);
  1566.         x2 = a2 - x(0);
  1567.         y2 = b2 - y(0);
  1568.  
  1569.         area = y2*x1 - x2*y1;
  1570.         area *= sign;
  1571.  
  1572.            if(area < 0.f)
  1573.            {
  1574.             first++;
  1575.             area = 0.f;
  1576.            }
  1577.     
  1578.            i = 1;
  1579.            do
  1580.            {
  1581.            float area2;
  1582.                sign = -sign; //reverse order
  1583.  
  1584.            x1 = a2 - a1;
  1585.            y1 = b2 - b1;
  1586.            x2 = x(i+2) - a1;
  1587.            y2 = y(i+2) - b1;
  1588.            a1 = a2;
  1589.            b1 = b2;
  1590.            a2 = x(i+2);
  1591.            b2 = y(i+2);
  1592.  
  1593.            area2 = y2*x1 - x2*y1;
  1594.            area2 *= sign;
  1595.  
  1596.             if(area2 < 0.f)
  1597.             {
  1598.                 if(first == i)    first++;
  1599.                 else        backface++;
  1600.             }
  1601.             else
  1602.             {
  1603.                 backface = 0;
  1604.                 area += area2;
  1605.             }
  1606.            i++;
  1607.            } while (i < size-2);
  1608.         size -= backface+first;
  1609.         }
  1610.        if (area < context->MinTriArea)
  1611.        return;
  1612.        }
  1613.  
  1614.     #undef x
  1615.     #undef y
  1616.  
  1617.     i = 0;
  1618.     do
  1619.     {
  1620.        verts[i] = &(context->VertexBuffer[first+i].v);
  1621.     i++;
  1622.     } while (i < size);
  1623.  
  1624.     PrepTexCoords(context, first, size, GL_FALSE);
  1625.  
  1626.     tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  1627.     tris.vertexcount = size;
  1628.     tris.v = &verts[0];
  1629.     tris.st_pattern = NULL;
  1630.  
  1631.     W3D_DrawTriStripV(context->w3dContext, &tris);
  1632.  
  1633.    return;
  1634.    }
  1635.  
  1636.  
  1637.     /*
  1638.     ** Up to now everything is like a polygon. Unlike a polygon, however,
  1639.     ** triangle fans and strips may be concave, and each individual triangle
  1640.     ** might be backfacing.
  1641.     **
  1642.     ** We calculate how many of the triangles are visible.
  1643.     */
  1644.  
  1645.     backface = 0;
  1646.  
  1647.    if(context->CullFace_State == GL_FALSE)
  1648.    {
  1649.     for (triangle=0; triangle<context->VertexBufferPointer - 2; triangle++)
  1650.     {
  1651.        local_or = context->VertexBuffer[triangle+0].outcode
  1652.                  | context->VertexBuffer[triangle+1].outcode
  1653.                  | context->VertexBuffer[triangle+2].outcode;
  1654.  
  1655.        local_and = context->VertexBuffer[triangle+0].outcode
  1656.                   & context->VertexBuffer[triangle+1].outcode
  1657.                   & context->VertexBuffer[triangle+2].outcode;
  1658.  
  1659.  
  1660.  // if the local and code is zero, we're not completely off screen.
  1661.        if (local_and == 0)
  1662.        {
  1663.         complete[triangle] = local_or; 
  1664.         visible[triangle] = GL_TRUE;
  1665.         backface = 0;
  1666.        }
  1667.        else
  1668.        {
  1669.         visible[triangle] = GL_FALSE;
  1670.         backface++;
  1671.        }
  1672.     }
  1673.    }
  1674.    else
  1675.    {
  1676.     for (triangle=0; triangle<context->VertexBufferPointer - 2; triangle++)
  1677.     {
  1678.        local_or = context->VertexBuffer[triangle].outcode
  1679.                  | context->VertexBuffer[triangle+1].outcode
  1680.                  | context->VertexBuffer[triangle+2].outcode;
  1681.  
  1682.        local_and = context->VertexBuffer[triangle].outcode
  1683.                   & context->VertexBuffer[triangle+1].outcode
  1684.                   & context->VertexBuffer[triangle+2].outcode;
  1685.  
  1686.  
  1687.  // if the local and code is zero, we're not completely off screen.
  1688.        if (local_and == 0)
  1689.        {
  1690.         complete[triangle] = local_or;
  1691.  
  1692.         if(local_or & MGL_CLIP_NEGW)
  1693.         { 
  1694.             visible[triangle] = GL_TRUE;
  1695.             backface = 0;
  1696.         }
  1697.         else
  1698.         {
  1699.             visible[triangle] = hc_DecideFrontface(context, &(context->VertexBuffer[triangle]), &(context->VertexBuffer[triangle+1]), &(context->VertexBuffer[triangle+2]));
  1700.  
  1701.             if(visible[triangle] == GL_FALSE)
  1702.                 backface++;
  1703.             else
  1704.                 backface = 0;
  1705.         }
  1706.        }
  1707.        else
  1708.        {
  1709.         visible[triangle] = GL_FALSE;
  1710.         backface++;
  1711.        }
  1712.  
  1713.        context->CurrentCullSign = -context->CurrentCullSign;
  1714.     }
  1715.    }
  1716.  
  1717.     context->CurrentCullSign = CurrentCullSign;
  1718.    
  1719. //early out:
  1720.     if(triangle == backface)
  1721.     return;
  1722.  
  1723.     context->VertexBufferPointer -= backface; //surgeon 260302
  1724.  
  1725.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  1726.  
  1727.     /*
  1728.     ** Draw...
  1729.     ** There are three cases:
  1730.     **
  1731.     ** 1) Triangle is partially visible
  1732.     ** 2) Triangle is fully visible
  1733.     ** 3) Triangle is invisible
  1734.     **
  1735.     ** In case 1, we draw the triangle with clip_ClipAndDrawPoly.
  1736.     ** In case 2, we collect a triangle fan/strip of maximum length
  1737.     ** and draw that directly
  1738.     ** in case 3... WE IGNORE IT! HA!
  1739.     */
  1740.  
  1741.     free = context->VertexBufferPointer;
  1742.     pnum = 0;
  1743.  
  1744.     triangle = 0;
  1745.     do
  1746.     {
  1747.  
  1748.         if (visible[triangle] == GL_FALSE) // case 3
  1749.         {
  1750.             triangle ++;
  1751.         }
  1752.         else
  1753.         {
  1754.             if (complete[triangle]) // case 1
  1755.             {
  1756.                 static MGLPolygon poly;
  1757.  
  1758.                 poly.numverts = 3;
  1759.                 poly.verts[0] = triangle + 0;
  1760.                 poly.verts[1] = triangle + 1;
  1761.                 poly.verts[2] = triangle + 2;
  1762.  
  1763.                 hc_ClipPoly(context, &poly, &clip[pnum], free, complete[triangle]);
  1764.  
  1765.                 if(clip[pnum].numverts)
  1766.                 {
  1767.                 clip[pnum].type = W3D_PRIMITIVE_TRIFAN;
  1768.                 free = clip[pnum].nextfree;
  1769.                 pnum++;
  1770.                 }
  1771.  
  1772.                 triangle++;
  1773.             }
  1774.             else
  1775.             {   // case 2 (the difficult part)
  1776.                 int k=3;
  1777.                 clip[pnum].verts[0] = triangle;
  1778.                 clip[pnum].verts[1] = triangle+1;
  1779.                 clip[pnum].verts[2] = triangle+2;
  1780.  
  1781.                 triangle++;
  1782.  
  1783.                 while (complete[triangle]==0 && visible[triangle] && triangle<context->VertexBufferPointer - 2 && k < 64)
  1784.                 {
  1785.                 clip[pnum].verts[k] = triangle+2;
  1786.  
  1787.                 k++; triangle++;
  1788.                 }
  1789.  
  1790.             clip[pnum].numverts = k;
  1791.             clip[pnum].type = W3D_PRIMITIVE_TRISTRIP;
  1792.             pnum++;
  1793.             }
  1794.         }
  1795.  
  1796.     } while (triangle<context->VertexBufferPointer - 2);
  1797.  
  1798.  
  1799. //Project to screen and Draw:
  1800.  
  1801.     visible[context->VertexBufferPointer-2] = GL_FALSE;
  1802.     visible[context->VertexBufferPointer-1] = GL_FALSE;
  1803.  
  1804.     //project clipverts without index lookup
  1805.  
  1806.     for(i=context->VertexBufferPointer; i<free; i++)
  1807.     {
  1808.         v_ToScreen(context, i);
  1809.     }
  1810.  
  1811.     tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  1812.     tris.st_pattern = NULL;
  1813.  
  1814.     j = 0; first = 0;
  1815.     do
  1816.     {
  1817.       PolyBuffer *p = &clip[j];
  1818.  
  1819.       for (i=0; i<p->numverts; i++)
  1820.       {
  1821.         int vert = p->verts[i];
  1822.  
  1823.         if(vert < context->VertexBufferPointer && visible[vert] < 2)
  1824.         {
  1825.            v_ToScreen(context, vert);
  1826.            visible[vert] = 2;
  1827.         }
  1828.  
  1829.       verts[i+first] = &(context->VertexBuffer[vert].v);
  1830.       }
  1831.  
  1832.       tris.vertexcount = p->numverts;
  1833.       tris.v = &verts[first];
  1834.  
  1835.       if(p->type == W3D_PRIMITIVE_TRIFAN)
  1836.       { 
  1837.           error = W3D_DrawTriFanV(context->w3dContext, &tris);
  1838.       }
  1839.       else
  1840.       {
  1841.           error = W3D_DrawTriStripV(context->w3dContext, &tris);
  1842.       }
  1843.  
  1844.     first += p->numverts;
  1845.     j++;
  1846.     } while (j < pnum);
  1847.  
  1848. #if 0
  1849.    if(context->Texture2D_State[1])
  1850.     Multitex_PolyBuffer(context, verts, pnum, GL_TRUE);
  1851. #endif
  1852.  
  1853. #else
  1854.         int i;
  1855.         ULONG error;
  1856.         static W3D_Vertex *verts[MGL_MAXVERTS];
  1857.         static W3D_TrianglesV tris;
  1858.  
  1859.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  1860.  
  1861.         for (i=0; i<context->VertexBufferPointer-1; i++)
  1862.         {
  1863.             v_ToScreen(context, i);
  1864.             verts[i] = &(context->VertexBuffer[i].v);
  1865.         }
  1866.  
  1867.         tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  1868.         tris.st_pattern = NULL;
  1869.         tris.vertexcount = context->VertexBufferPointer-1;
  1870.         tris.v = verts;
  1871.         #ifndef NODRAW
  1872.         error = W3D_DrawTriStripV(context->w3dContext, &tris);
  1873.         #endif
  1874. #endif
  1875. }
  1876.  
  1877. void d_DrawQuadStrip(GLcontext context)
  1878. {
  1879. #if !defined(DISABLE_TRANSFORMATION)
  1880.     int i,j;
  1881.     ULONG or_code, and_code;
  1882.     ULONG error;
  1883.  
  1884.     static W3D_Vertex *verts[4];
  1885.     static W3D_TrianglesV tris;
  1886.  
  1887.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  1888.     return;
  1889.  
  1890.     v_Transform(context);
  1891.  
  1892.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  1893.  
  1894.     for (j=0; j<context->VertexBufferPointer; j++)
  1895.     {
  1896.         MGLVertex *v = &(context->VertexBuffer[j]);
  1897.         float w = v->bw;
  1898.         ULONG outcode = 0;
  1899.  
  1900.         if (w < CLIP_EPS )
  1901.         {
  1902.             outcode |= MGL_CLIP_NEGW;
  1903.         }
  1904.  
  1905.         if (-w > v->bx)
  1906.         {
  1907.             outcode |= MGL_CLIP_LEFT;
  1908.         }
  1909.         else if (v->bx > w)
  1910.         {
  1911.             outcode |= MGL_CLIP_RIGHT;
  1912.         }
  1913.  
  1914.         if (-w > v->by)
  1915.         {
  1916.             outcode |= MGL_CLIP_BOTTOM;
  1917.         }
  1918.         else if (v->by > w)
  1919.         {
  1920.             outcode |= MGL_CLIP_TOP;
  1921.         }
  1922.     
  1923.         if (-w > v->bz)
  1924.         {
  1925.             outcode |= MGL_CLIP_BACK;
  1926.         }
  1927.         else if (v->bz > w)
  1928.         {
  1929.             outcode |= MGL_CLIP_FRONT;
  1930.         }
  1931.  
  1932.         v->outcode = outcode;
  1933.     }
  1934.  
  1935.  
  1936.     for (i=0; i<context->VertexBufferPointer-2; i+=2)
  1937.     {
  1938.         or_code = context->VertexBuffer[i+0].outcode
  1939.                 | context->VertexBuffer[i+1].outcode
  1940.                 | context->VertexBuffer[i+2].outcode
  1941.                 | context->VertexBuffer[i+3].outcode;
  1942.  
  1943.         and_code = context->VertexBuffer[i+0].outcode
  1944.                  & context->VertexBuffer[i+1].outcode
  1945.                  & context->VertexBuffer[i+2].outcode
  1946.                  & context->VertexBuffer[i+3].outcode;
  1947.  
  1948.         if (and_code) continue;
  1949.  
  1950.         if(context->CullFace_State == GL_TRUE && !(or_code & MGL_CLIP_NEGW))
  1951.         {
  1952.             if (hc_DecideFrontface(context, &(context->VertexBuffer[i]),
  1953.             &(context->VertexBuffer[i+1]),
  1954.             &(context->VertexBuffer[i+2])) == GL_FALSE) continue;
  1955.         }
  1956.  
  1957.         if (or_code == 0)
  1958.         {
  1959.             v_ToScreen(context, i);
  1960.             v_ToScreen(context, i+1);
  1961.             v_ToScreen(context, i+2);
  1962.             v_ToScreen(context, i+3);
  1963.  
  1964.             verts[0] = &(context->VertexBuffer[i+0].v);
  1965.             verts[1] = &(context->VertexBuffer[i+1].v);
  1966.             verts[2] = &(context->VertexBuffer[i+3].v);
  1967.             verts[3] = &(context->VertexBuffer[i+2].v);
  1968.             tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  1969.             tris.st_pattern = NULL;
  1970.             tris.vertexcount = 4;
  1971.             tris.v = verts;
  1972.  
  1973.             error = W3D_DrawTriFanV(context->w3dContext, &tris);
  1974.         }
  1975.         else
  1976.         {
  1977.             static MGLPolygon poly;
  1978.             poly.numverts = 4;
  1979.             poly.verts[0] = i;
  1980.             poly.verts[1] = i+1;
  1981.             poly.verts[2] = i+3;
  1982.             poly.verts[3] = i+2;
  1983.  
  1984.             hc_ClipAndDrawPoly(context, &poly, or_code);
  1985.         }
  1986.     }
  1987. #else
  1988.     int i;
  1989.     ULONG error;
  1990.     static W3D_Vertex *verts[4];
  1991.     static W3D_TrianglesV tris;
  1992.  
  1993.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  1994.  
  1995.     for (i=0; i<context->VertexBufferPointer-2; i+=2)
  1996.     {
  1997.         v_ToScreen(context, i);
  1998.         v_ToScreen(context, i+1);
  1999.         v_ToScreen(context, i+2);
  2000.         v_ToScreen(context, i+3);
  2001.  
  2002.         verts[0] = &(context->VertexBuffer[i+0].v);
  2003.         verts[1] = &(context->VertexBuffer[i+1].v);
  2004.         verts[2] = &(context->VertexBuffer[i+3].v);
  2005.         verts[3] = &(context->VertexBuffer[i+2].v);
  2006.         tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  2007.         tris.st_pattern = NULL;
  2008.         tris.vertexcount = 4;
  2009.         tris.v = verts;
  2010.  
  2011.         error = W3D_DrawTriFanV(context->w3dContext, &tris);
  2012.        }
  2013. #endif
  2014. }
  2015.  
  2016. void d_DrawQuads(GLcontext context)
  2017. {
  2018. #if !defined(DISABLE_TRANSFORMATION)
  2019.     int i,j;
  2020.     ULONG or_code, and_code;
  2021.     ULONG error;
  2022.     static W3D_Vertex *verts[4];
  2023.     static W3D_TrianglesV tris;
  2024.  
  2025.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  2026.     return;
  2027.  
  2028.     v_Transform(context);
  2029.  
  2030.     for (i=0; i<context->VertexBufferPointer; i+=4)
  2031.     {
  2032.        for (j=i; j<i+4;j++)
  2033.        {
  2034.         MGLVertex *v = &(context->VertexBuffer[j]);
  2035.         float w = v->bw;
  2036.         ULONG outcode = 0;
  2037.  
  2038.         if (w < CLIP_EPS )
  2039.         {
  2040.             outcode |= MGL_CLIP_NEGW;
  2041.         }
  2042.  
  2043.         if (-w > v->bx)
  2044.         {
  2045.             outcode |= MGL_CLIP_LEFT;
  2046.         }
  2047.         else if (v->bx > w)
  2048.         {
  2049.             outcode |= MGL_CLIP_RIGHT;
  2050.         }
  2051.  
  2052.         if (-w > v->by)
  2053.         {
  2054.             outcode |= MGL_CLIP_BOTTOM;
  2055.         }
  2056.         else if (v->by > w)
  2057.         {
  2058.             outcode |= MGL_CLIP_TOP;
  2059.         }
  2060.     
  2061.         if (-w > v->bz)
  2062.         {
  2063.             outcode |= MGL_CLIP_BACK;
  2064.         }
  2065.         else if (v->bz > w)
  2066.         {
  2067.             outcode |= MGL_CLIP_FRONT;
  2068.         }
  2069.  
  2070.         v->outcode = outcode;
  2071.       }
  2072.  
  2073.         or_code = context->VertexBuffer[i+0].outcode
  2074.                 | context->VertexBuffer[i+1].outcode
  2075.                 | context->VertexBuffer[i+2].outcode
  2076.                 | context->VertexBuffer[i+3].outcode;
  2077.  
  2078.         and_code = context->VertexBuffer[i+0].outcode
  2079.                  & context->VertexBuffer[i+1].outcode
  2080.                  & context->VertexBuffer[i+2].outcode
  2081.                  & context->VertexBuffer[i+3].outcode;
  2082.  
  2083.         if (and_code) continue;
  2084.  
  2085.  
  2086.         if(context->CullFace_State == GL_TRUE && !(or_code & MGL_CLIP_NEGW))
  2087.         {
  2088.             if (hc_DecideFrontface(context, &(context->VertexBuffer[i]),
  2089.             &(context->VertexBuffer[i+1]),
  2090.             &(context->VertexBuffer[i+2])) == GL_FALSE) continue;
  2091.         }
  2092.  
  2093.         PrepTexCoords(context, i, 4, GL_FALSE);
  2094.  
  2095.         if (or_code == 0)
  2096.         {
  2097.             v_ToScreen(context, i);
  2098.             v_ToScreen(context, i+1);
  2099.             v_ToScreen(context, i+2);
  2100.             v_ToScreen(context, i+3);
  2101.  
  2102.             verts[0] = &(context->VertexBuffer[i+0].v);
  2103.             verts[1] = &(context->VertexBuffer[i+1].v);
  2104.             verts[2] = &(context->VertexBuffer[i+2].v);
  2105.             verts[3] = &(context->VertexBuffer[i+3].v);
  2106.             tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  2107.             tris.st_pattern = NULL;
  2108.             tris.vertexcount = 4;
  2109.             tris.v = verts;
  2110.             #ifndef NODRAW
  2111.             error = W3D_DrawTriFanV(context->w3dContext, &tris);
  2112.             #else
  2113.             printf("d_DrawQuads\n");
  2114.             DUMP_VERTEX(context->VertexBuffer[i+0]);
  2115.             DUMP_VERTEX(context->VertexBuffer[i+1]);
  2116.             DUMP_VERTEX(context->VertexBuffer[i+2]);
  2117.             DUMP_VERTEX(context->VertexBuffer[i+3]);
  2118.             printf("-----------------------------------\n");
  2119.             #endif
  2120.         }
  2121.         else
  2122.         {
  2123.             static MGLPolygon poly;
  2124.             poly.numverts = 4;
  2125.             poly.verts[0] = i;
  2126.             poly.verts[1] = i+1;
  2127.             poly.verts[2] = i+2;
  2128.             poly.verts[3] = i+3;
  2129.             hc_ClipAndDrawPoly(context, &poly, or_code);
  2130.         }
  2131.     }
  2132.  
  2133. #else
  2134.     int i;
  2135.     ULONG error;
  2136.     static W3D_Vertex *verts[4];
  2137.     static W3D_TrianglesV tris;
  2138.  
  2139.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  2140.  
  2141.     for (i=0; i<context->VertexBufferPointer; i+=4)
  2142.     {
  2143.         v_ToScreen(context, i);
  2144.         v_ToScreen(context, i+1);
  2145.         v_ToScreen(context, i+2);
  2146.         v_ToScreen(context, i+3);
  2147.  
  2148.         verts[0] = &(context->VertexBuffer[i+0].v);
  2149.         verts[1] = &(context->VertexBuffer[i+1].v);
  2150.         verts[2] = &(context->VertexBuffer[i+2].v);
  2151.         verts[3] = &(context->VertexBuffer[i+3].v);
  2152.         tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  2153.         tris.st_pattern = NULL;
  2154.         tris.vertexcount = 4;
  2155.         tris.v = verts;
  2156.  
  2157.         error = W3D_DrawTriFanV(context->w3dContext, &tris);
  2158.        }
  2159. #endif
  2160. }
  2161.  
  2162.  
  2163.  
  2164. //For chaining and buffering multitexture-polys:
  2165.  
  2166. typedef struct MtexPolyIdx_s
  2167. {
  2168.     W3D_Texture    *tmu[2];
  2169.     GLuint        first;
  2170.     GLuint        count;
  2171.  
  2172. } MtexPolyIdx;
  2173.  
  2174.  
  2175. //alternative to W3D_Vertex:
  2176.  
  2177. typedef struct W3D_VAVertex_s
  2178. {
  2179.     float x,y,z,w;
  2180.     float s1,t1,s2,t2;
  2181.     ULONG color;
  2182.     ULONG _pad_[3]; //16 byte align
  2183.  
  2184. } W3D_VAVertex;
  2185.  
  2186.  
  2187. #define MTEX_INDEXSIZE 1024
  2188. #define MTEX_VERTEXBUFFERSIZE 4096
  2189.  
  2190. static MtexPolyIdx pidx[MTEX_INDEXSIZE];
  2191. static int polypointer = 0;
  2192.  
  2193. static W3D_VAVertex *mtex_pbuffer = NULL;
  2194.  
  2195. GLboolean AllocMtex()
  2196. {
  2197.     int i;
  2198.  
  2199.     if(mtex_pbuffer == NULL)
  2200.     {
  2201.         mtex_pbuffer = (W3D_VAVertex *) malloc( sizeof(W3D_VAVertex) * MTEX_VERTEXBUFFERSIZE);
  2202.     }
  2203.  
  2204.     if(!mtex_pbuffer)
  2205.         return GL_FALSE;
  2206.  
  2207.     return GL_TRUE;
  2208. }
  2209.  
  2210. void FreeMtex(void)
  2211. {
  2212.     if(mtex_pbuffer) free(mtex_pbuffer);
  2213. }
  2214.  
  2215. #define CPACK(r,g,b,a) \
  2216. (ULONG)( (((ULONG)((a)*255.f))<<24) | (((ULONG)((r)*255.f))<<16) | (((ULONG)((g)*255.f))<<8) | ((ULONG)(b*255.f)) )
  2217.  
  2218.  
  2219. static void v_MtexToScreen_Flat(GLcontext context, int i, int bufpointer)
  2220. {
  2221.     float x,y,z,w;
  2222.     float az;
  2223.  
  2224.     if (context->ZOffset_State == GL_TRUE)
  2225.         az = context->az + context->ZOffset;
  2226.     else
  2227.         az = context->az;
  2228.  
  2229.     w = 1.0 / context->VertexBuffer[i].bw;
  2230.  
  2231.     x = context->ax + context->VertexBuffer[i].bx * w * context->sx;
  2232.     y = context->ay - context->VertexBuffer[i].by * w * context->sy;
  2233.     z = az + context->VertexBuffer[i].bz * w * context->sz;
  2234.  
  2235.     mtex_pbuffer[bufpointer].x = x;
  2236.     mtex_pbuffer[bufpointer].y = y;
  2237.     mtex_pbuffer[bufpointer].z = z;
  2238.     mtex_pbuffer[bufpointer].w = w;
  2239.  
  2240.     mtex_pbuffer[bufpointer].s1 = context->VertexBuffer[i].v.u;
  2241.     mtex_pbuffer[bufpointer].t1 = context->VertexBuffer[i].v.v;
  2242.  
  2243.     mtex_pbuffer[bufpointer].s2 = context->VertexBuffer[i].tcoord.s;
  2244.     mtex_pbuffer[bufpointer].t2 = context->VertexBuffer[i].tcoord.t;
  2245.  
  2246. }
  2247.  
  2248. static void v_MtexToScreen_Smooth(GLcontext context, int i, int bufpointer)
  2249. {
  2250.     float x,y,z,w;
  2251.     float az;
  2252.  
  2253.     if (context->ZOffset_State == GL_TRUE)
  2254.         az = context->az + context->ZOffset;
  2255.     else
  2256.         az = context->az;
  2257.  
  2258.     w = 1.0 / context->VertexBuffer[i].bw;
  2259.  
  2260.     x = context->ax + context->VertexBuffer[i].bx * w * context->sx;
  2261.     y = context->ay - context->VertexBuffer[i].by * w * context->sy;
  2262.     z = az + context->VertexBuffer[i].bz * w * context->sz;
  2263.     mtex_pbuffer[bufpointer].x = x;
  2264.     mtex_pbuffer[bufpointer].y = y;
  2265.     mtex_pbuffer[bufpointer].z = z;
  2266.     mtex_pbuffer[bufpointer].w = w;
  2267.  
  2268.     mtex_pbuffer[bufpointer].s1 = context->VertexBuffer[i].v.u ;
  2269.     mtex_pbuffer[bufpointer].t1 = context->VertexBuffer[i].v.v ;
  2270.  
  2271.     mtex_pbuffer[bufpointer].s2 = context->VertexBuffer[i].tcoord.s;
  2272.     mtex_pbuffer[bufpointer].t2 = context->VertexBuffer[i].tcoord.t;
  2273.  
  2274.     mtex_pbuffer[bufpointer].color = CPACK(context->VertexBuffer[i].v.color.r, context->VertexBuffer[i].v.color.g, context->VertexBuffer[i].v.color.b, context->VertexBuffer[i].v.color.a);
  2275. }
  2276.  
  2277. static void ProjectMtex_Flat(GLcontext context, int numverts, int bufstart)
  2278. {
  2279.     int i;
  2280.     int bufpointer;
  2281.     float az;
  2282.     float x,y,z,w;
  2283.  
  2284.     if (context->ZOffset_State == GL_TRUE)
  2285.         az = context->az + context->ZOffset;
  2286.     else
  2287.         az = context->az;
  2288.  
  2289.     i = 0;
  2290.     bufpointer = bufstart;
  2291.  
  2292.     do
  2293.     {
  2294.     w = 1.0 / context->VertexBuffer[i].bw;
  2295.  
  2296.     x = context->ax + context->VertexBuffer[i].bx * w * context->sx;
  2297.     y = context->ay - context->VertexBuffer[i].by * w * context->sy;
  2298.     z = az + context->VertexBuffer[i].bz * w * context->sz;
  2299.  
  2300.     mtex_pbuffer[bufpointer].x = x;
  2301.     mtex_pbuffer[bufpointer].y = y;
  2302.     mtex_pbuffer[bufpointer].z = z;
  2303.     mtex_pbuffer[bufpointer].w = w;
  2304.  
  2305.     mtex_pbuffer[bufpointer].s1 = context->VertexBuffer[i].v.u;
  2306.     mtex_pbuffer[bufpointer].t1 = context->VertexBuffer[i].v.v;
  2307.  
  2308.     mtex_pbuffer[bufpointer].s2 = context->VertexBuffer[i].tcoord.s;
  2309.     mtex_pbuffer[bufpointer].t2 = context->VertexBuffer[i].tcoord.t;
  2310.  
  2311.     i++; bufpointer++;
  2312.     } while (i < numverts);
  2313.  
  2314. }
  2315.  
  2316. static void ProjectMtex_Smooth(GLcontext context, int numverts, int bufstart)
  2317. {
  2318.     int i;
  2319.     int bufpointer;
  2320.     float az;
  2321.     float x,y,z,w;
  2322.  
  2323.     if (context->ZOffset_State == GL_TRUE)
  2324.         az = context->az + context->ZOffset;
  2325.     else
  2326.         az = context->az;
  2327.  
  2328.     i = 0;
  2329.     bufpointer = bufstart;
  2330.  
  2331.     do
  2332.     {
  2333.     w = 1.0 / context->VertexBuffer[i].bw;
  2334.  
  2335.     x = context->ax + context->VertexBuffer[i].bx * w * context->sx;
  2336.     y = context->ay - context->VertexBuffer[i].by * w * context->sy;
  2337.     z = az + context->VertexBuffer[i].bz * w * context->sz;
  2338.     mtex_pbuffer[bufpointer].x = x;
  2339.     mtex_pbuffer[bufpointer].y = y;
  2340.     mtex_pbuffer[bufpointer].z = z;
  2341.     mtex_pbuffer[bufpointer].w = w;
  2342.  
  2343.     mtex_pbuffer[bufpointer].s1 = context->VertexBuffer[i].v.u;
  2344.     mtex_pbuffer[bufpointer].t1 = context->VertexBuffer[i].v.v;
  2345.  
  2346.     mtex_pbuffer[bufpointer].s2 = context->VertexBuffer[i].tcoord.s;
  2347.     mtex_pbuffer[bufpointer].t2 = context->VertexBuffer[i].tcoord.t;
  2348.  
  2349.     mtex_pbuffer[bufpointer].color = CPACK(context->VertexBuffer[i].v.color.r, context->VertexBuffer[i].v.color.g, context->VertexBuffer[i].v.color.b, context->VertexBuffer[i].v.color.a);
  2350.  
  2351.     i++; bufpointer++;
  2352.     } while (i < numverts);
  2353.  
  2354. }
  2355.  
  2356.  
  2357. void d_DrawSmoothPoly(GLcontext context)
  2358. {
  2359.     int i,j;
  2360.     ULONG and_code, or_code, local_or, guard_band;
  2361.     ULONG error;
  2362.     static MGLPolygon poly;
  2363.     static W3D_Vertex **verts = NULL;
  2364.     static W3D_TrianglesV fan;
  2365.     static ULONG complete[MGL_MAXVERTS];
  2366.     int triangle;
  2367.     int nocull;
  2368.     int pnum, free;
  2369.  
  2370.     if(context->VertexBufferPointer < 3)
  2371.         return;
  2372.  
  2373.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  2374.         return;
  2375.  
  2376.     v_Transform(context);
  2377.  
  2378.     and_code = 0xff; or_code = 0;
  2379.  
  2380.     for (i=0; i<context->VertexBufferPointer; i++)
  2381.     {
  2382.         MGLVertex *v = &(context->VertexBuffer[i]);
  2383.         float w = v->bw;
  2384.         ULONG outcode = 0;
  2385.  
  2386.         if (w < CLIP_EPS )
  2387.         {
  2388.             outcode |= MGL_CLIP_NEGW;
  2389.         }
  2390.  
  2391.         if (-w > v->bx)
  2392.         {
  2393.             outcode |= MGL_CLIP_LEFT;
  2394.         }
  2395.         else if (v->bx > w)
  2396.         {
  2397.             outcode |= MGL_CLIP_RIGHT;
  2398.         }
  2399.  
  2400.         if (-w > v->by)
  2401.         {
  2402.             outcode |= MGL_CLIP_BOTTOM;
  2403.         }
  2404.         else if (v->by > w)
  2405.         {
  2406.             outcode |= MGL_CLIP_TOP;
  2407.         }
  2408.     
  2409.         if (-w > v->bz)
  2410.         {
  2411.             outcode |= MGL_CLIP_BACK;
  2412.         }
  2413.         else if (v->bz > w)
  2414.         {
  2415.             outcode |= MGL_CLIP_FRONT;
  2416.         }
  2417.  
  2418.         v->outcode = outcode;
  2419.         and_code &= outcode;
  2420.         or_code |= outcode;
  2421.  
  2422.         poly.verts[i] = i;
  2423.     }
  2424.  
  2425.    if (and_code)
  2426.     return;
  2427.  
  2428.  
  2429.    if (verts == NULL)
  2430.    {
  2431.         verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  2432.         if (!verts) return;
  2433.    }
  2434.  
  2435.  
  2436.    poly.numverts = context->VertexBufferPointer;
  2437.  
  2438.  
  2439. #if defined(PRIORITIZE_BANDWIDTH) || defined(PRIORITIZE_FILRATE)
  2440.  
  2441.    //try to shrink primitive:
  2442.  
  2443.    if(context->VertexBuffer[0].outcode && poly.numverts > 3)
  2444.    {
  2445.     ULONG local_and;
  2446.     int size;
  2447.     int first;
  2448.  
  2449.     first = 0;
  2450.     i = poly.numverts - 2;
  2451.  
  2452.     local_and = context->VertexBuffer[0].outcode & context->VertexBuffer[i].outcode & context->VertexBuffer[i+1].outcode;
  2453.  
  2454.     if(local_and)
  2455.     {
  2456.         i--;
  2457.  
  2458.         while (i)
  2459.         {
  2460.            if((local_and & context->VertexBuffer[i].outcode) == 0)
  2461.             break;
  2462.  
  2463.            i--;
  2464.         }
  2465.     }
  2466.  
  2467.     size = i+2;
  2468.  
  2469.     if(size > 3)
  2470.     {
  2471.        i = 1;
  2472.  
  2473.        local_and = context->VertexBuffer[0].outcode & context->VertexBuffer[i].outcode & context->VertexBuffer[i+1].outcode;
  2474.  
  2475.        if(local_and)
  2476.        {
  2477.         i++;
  2478.  
  2479.         while (i < size-2)
  2480.         {
  2481.            if((local_and & context->VertexBuffer[i+1].outcode) == 0)
  2482.             break;
  2483.            i++;
  2484.         }
  2485.        }
  2486.  
  2487.        first = i-1;
  2488.     }
  2489.  
  2490.     if((size < poly.numverts) || first)
  2491.     {
  2492.        context->VertexBufferPointer = size;
  2493.  
  2494.        poly.numverts = size - first;
  2495.  
  2496.        or_code = context->VertexBuffer[0].outcode;
  2497.     
  2498.        i = 1;
  2499.        do
  2500.        {
  2501.         poly.verts[i] = first+i;
  2502.         or_code |= context->VertexBuffer[first+i].outcode;
  2503.  
  2504.        i++;
  2505.        } while (i < poly.numverts);
  2506.     }
  2507.    }
  2508.  
  2509. #endif
  2510.  
  2511. //guardband-test:
  2512.  
  2513.    if(or_code == 0 || (or_code & context->ClipFlags))
  2514.    {
  2515.     guard_band = or_code;
  2516.    }
  2517.    else
  2518.    {
  2519.     guard_band = 0;
  2520.     i = 0;
  2521.  
  2522.     do
  2523.     {
  2524.       MGLVertex *v = &context->VertexBuffer[poly.verts[i]];
  2525.  
  2526.        if(v->outcode)
  2527.        {
  2528.        float gcw = v->bw * 2.0;
  2529.  
  2530.        if (-gcw > v->bx)
  2531.         guard_band |= MGL_CLIP_LEFT;
  2532.        else if (v->bx > gcw)
  2533.         guard_band |= MGL_CLIP_RIGHT;
  2534.  
  2535.        if (-gcw > v->by)
  2536.         guard_band |= MGL_CLIP_BOTTOM;
  2537.        else if (v->by > gcw)
  2538.         guard_band |= MGL_CLIP_TOP;
  2539.        }
  2540.     i++;
  2541.     } while (i < poly.numverts && guard_band == 0);
  2542.  
  2543.    }
  2544.  
  2545.    if(guard_band == 0)
  2546.    {
  2547.     int vert;
  2548.  
  2549.     if( poly.numverts == 3 && context->CullFace_State == GL_TRUE)
  2550.     {
  2551.         if( hc_DecideFrontface(context, &context->VertexBuffer[0], &context->VertexBuffer[poly.verts[1]], &context->VertexBuffer[poly.verts[1] + 1]) == GL_FALSE)
  2552.         return;
  2553.     }
  2554.  
  2555.     PrepTexCoords(context, poly.verts[1], poly.numverts, GL_TRUE);
  2556.  
  2557.  
  2558.     verts[0] = &(context->VertexBuffer[0].v);
  2559.     v_ToScreen(context, 0);
  2560.  
  2561.     vert = poly.verts[1];
  2562.     i = 1;
  2563.  
  2564.     do
  2565.     {
  2566.         verts[i] = &(context->VertexBuffer[vert].v);
  2567.         v_ToScreen(context, vert);
  2568.  
  2569.     i++; vert++;
  2570.     } while (i < poly.numverts);
  2571.  
  2572.  
  2573.     fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  2574.     fan.st_pattern = NULL;
  2575.     fan.v = verts;
  2576.     fan.vertexcount = poly.numverts;
  2577.  
  2578.     error = W3D_DrawTriFanV(context->w3dContext, &fan);
  2579.  
  2580.     return;
  2581.    }
  2582.  
  2583.    i = poly.verts[1];
  2584.    triangle = 0;
  2585.  
  2586.    if(context->CullFace_State == GL_FALSE)
  2587.    {
  2588.     do
  2589.     {
  2590.         complete[triangle] = context->VertexBuffer[0].outcode | context->VertexBuffer[i].outcode | context->VertexBuffer[i+1].outcode;
  2591.  
  2592.     triangle++; i++;
  2593.     } while (i < context->VertexBufferPointer-1);
  2594.    }
  2595.    else
  2596.    {
  2597.     nocull = 0;
  2598.  
  2599.     do
  2600.     {
  2601.         local_or = context->VertexBuffer[0].outcode
  2602.             | context->VertexBuffer[i].outcode
  2603.             | context->VertexBuffer[i+1].outcode;
  2604.  
  2605.         complete[triangle] = local_or;
  2606.  
  2607.         if(local_or & MGL_CLIP_NEGW)
  2608.         {
  2609.            nocull = 1;
  2610.         }
  2611.         else if(nocull == 0)
  2612.         {
  2613.            if(hc_DecideFrontface(context, &context->VertexBuffer[0], &context->VertexBuffer[i], &context->VertexBuffer[i+1]) == GL_TRUE)
  2614.            {
  2615.             nocull = 1;
  2616.            }
  2617.         }
  2618.  
  2619.     i++; triangle++;
  2620.     } while (i < context->VertexBufferPointer - 1);
  2621.     
  2622. //early out:
  2623.     if(nocull == 0)
  2624.         return;
  2625.    }
  2626.  
  2627.     PrepTexCoords(context, poly.verts[1], poly.numverts, GL_TRUE);
  2628.  
  2629.     i = poly.verts[1];
  2630.     triangle = 0;
  2631.     free = context->VertexBufferPointer;
  2632.     pnum = 0;
  2633.  
  2634.     do
  2635.     {
  2636.         if (complete[triangle]) // case 1
  2637.         {
  2638.             static MGLPolygon cpoly;
  2639.  
  2640.             cpoly.numverts = 3;
  2641.             cpoly.verts[0] = 0;
  2642.             cpoly.verts[1] = i;
  2643.             cpoly.verts[2] = i + 1;
  2644.  
  2645.             hc_ClipPoly(context, &cpoly, &clip[pnum], free, complete[triangle]);
  2646.  
  2647.             if(clip[pnum].numverts)
  2648.             {
  2649.                 free = clip[pnum].nextfree;
  2650.                 pnum++;
  2651.             }
  2652.  
  2653.             i++; triangle++;
  2654.         }
  2655.         else
  2656.         {   // case 2 (the difficult part)
  2657.             int k=3;
  2658.             clip[pnum].verts[0] = 0;
  2659.             clip[pnum].verts[1] = i;
  2660.             clip[pnum].verts[2] = i+1;
  2661.  
  2662.             triangle ++;
  2663.             i        ++;
  2664.  
  2665.             while (complete[triangle]==0 && i<context->VertexBufferPointer - 1)
  2666.             {
  2667.                 clip[pnum].verts[k] = i+1;
  2668.                 i++; k++; triangle++;
  2669.             }
  2670.         clip[pnum].numverts = k;
  2671.         pnum++;
  2672.         }
  2673.  
  2674.     } while (i<context->VertexBufferPointer-1);
  2675.  
  2676.  
  2677.    //project clipverts
  2678.  
  2679.    // mark unprojected verts within the vertexbuffer-range
  2680.  
  2681.    for(i=0; i<context->VertexBufferPointer; i++)
  2682.    {
  2683.     complete[i] = 0;
  2684.    }
  2685.  
  2686.    for(i=context->VertexBufferPointer; i<free; i++)
  2687.    {
  2688.     v_ToScreen(context, i);
  2689.    }
  2690.  
  2691.    fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  2692.    fan.st_pattern = NULL;
  2693.    fan.v = verts;
  2694.  
  2695.    j = 0;
  2696.    do
  2697.    {
  2698.     PolyBuffer *p = &clip[j];
  2699.  
  2700.     for (i=0; i<p->numverts; i++)
  2701.     {
  2702.        int vert = p->verts[i];
  2703.  
  2704.        if(vert < context->VertexBufferPointer && complete[vert] == 0)
  2705.        {
  2706.         complete[vert] = 1;
  2707.         v_ToScreen(context, vert);
  2708.        }
  2709.  
  2710.     verts[i] = &(context->VertexBuffer[vert].v);
  2711.     }
  2712.  
  2713.     fan.vertexcount = p->numverts;
  2714.     error = W3D_DrawTriFanV(context->w3dContext, &fan);
  2715.  
  2716.    } while (++j < pnum);
  2717. }
  2718.  
  2719.  
  2720. void d_DrawMtexPoly(GLcontext context)
  2721. {
  2722.    int i,j;
  2723.    ULONG and_code, or_code, guard_band;
  2724.    static MGLPolygon poly;
  2725.    static int mtexverts;
  2726.    static int start;
  2727.  
  2728.     if(context->VertexBufferPointer < 3)
  2729.         return;
  2730.  
  2731.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  2732.         return;
  2733.  
  2734.     v_Transform(context);
  2735.  
  2736.     and_code = 0xff; or_code = 0;
  2737.  
  2738.     for (i=0; i<context->VertexBufferPointer; i++)
  2739.     {
  2740.         MGLVertex *v = &(context->VertexBuffer[i]);
  2741.         float w = v->bw;
  2742.         ULONG outcode = 0;
  2743.  
  2744.         if (w < CLIP_EPS )
  2745.         {
  2746.             outcode |= MGL_CLIP_NEGW;
  2747.         }
  2748.  
  2749.         if (-w > v->bx)
  2750.         {
  2751.             outcode |= MGL_CLIP_LEFT;
  2752.         }
  2753.         else if (v->bx > w)
  2754.         {
  2755.             outcode |= MGL_CLIP_RIGHT;
  2756.         }
  2757.  
  2758.         if (-w > v->by)
  2759.         {
  2760.             outcode |= MGL_CLIP_BOTTOM;
  2761.         }
  2762.         else if (v->by > w)
  2763.         {
  2764.             outcode |= MGL_CLIP_TOP;
  2765.         }
  2766.     
  2767.         if (-w > v->bz)
  2768.         {
  2769.             outcode |= MGL_CLIP_BACK;
  2770.         }
  2771.         else if (v->bz > w)
  2772.         {
  2773.             outcode |= MGL_CLIP_FRONT;
  2774.         }
  2775.  
  2776.         v->outcode = outcode;
  2777.         and_code &= outcode;
  2778.         or_code |= outcode;
  2779.  
  2780.         poly.verts[i] = i;
  2781.     }
  2782.  
  2783.     if (and_code)
  2784.     return;
  2785.  
  2786.     poly.numverts = context->VertexBufferPointer;
  2787.  
  2788. #if defined(PRIORITIZE_BANDWIDTH) || defined(PRIORITIZE_FILRATE)
  2789.  
  2790.    //try to shrink primitive:
  2791.  
  2792.    if(context->VertexBuffer[0].outcode && poly.numverts > 3)
  2793.    {
  2794.     ULONG local_and;
  2795.     int size;
  2796.     int first;
  2797.  
  2798.     first = 0;
  2799.     i = poly.numverts - 2;
  2800.  
  2801.     local_and = context->VertexBuffer[0].outcode & context->VertexBuffer[i].outcode & context->VertexBuffer[i+1].outcode;
  2802.  
  2803.     if(local_and)
  2804.     {
  2805.         i--;
  2806.  
  2807.         while (i)
  2808.         {
  2809.            if((local_and & context->VertexBuffer[i].outcode) == 0)
  2810.             break;
  2811.  
  2812.            i--;
  2813.         }
  2814.     }
  2815.  
  2816.     size = i+2;
  2817.  
  2818.     if(size > 3)
  2819.     {
  2820.        i = 1;
  2821.  
  2822.        local_and = context->VertexBuffer[0].outcode & context->VertexBuffer[i].outcode & context->VertexBuffer[i+1].outcode;
  2823.  
  2824.        if(local_and)
  2825.        {
  2826.         i++;
  2827.  
  2828.         while (i < size-2)
  2829.         {
  2830.            if((local_and & context->VertexBuffer[i+1].outcode) == 0)
  2831.             break;
  2832.            i++;
  2833.         }
  2834.        }
  2835.  
  2836.        first = i-1;
  2837.     }
  2838.  
  2839.     if((size < poly.numverts) || first)
  2840.     {
  2841.        context->VertexBufferPointer = size;
  2842.  
  2843.        poly.numverts = size - first;
  2844.  
  2845.        or_code = context->VertexBuffer[0].outcode;
  2846.     
  2847.        i = 1;
  2848.        do
  2849.        {
  2850.         poly.verts[i] = first+i;
  2851.         or_code |= context->VertexBuffer[first+i].outcode;
  2852.  
  2853.        i++;
  2854.        } while (i < poly.numverts);
  2855.     }
  2856.    }
  2857.  
  2858. #endif
  2859.  
  2860.  
  2861.    if( poly.numverts == 3 && context->CullFace_State == GL_TRUE && !(or_code & MGL_CLIP_NEGW) )
  2862.    {
  2863.     if( hc_DecideFrontface(context, &context->VertexBuffer[0], &context->VertexBuffer[poly.verts[1]], &context->VertexBuffer[poly.verts[1] + 1]) == GL_FALSE)
  2864.         return;
  2865.    }
  2866.  
  2867.  
  2868. //guardband-test
  2869.  
  2870.    if(or_code == 0 || (or_code & context->ClipFlags))
  2871.    {
  2872.        guard_band = or_code;
  2873.    }
  2874.    else
  2875.    {
  2876.     i = 0;
  2877.     guard_band = 0;
  2878.  
  2879.     do
  2880.     {
  2881.       MGLVertex *v = &context->VertexBuffer[poly.verts[i]];
  2882.  
  2883.        if(v->outcode)
  2884.        {
  2885.        float gcw = v->bw * 2.0;
  2886.  
  2887.        if (-gcw > v->bx)
  2888.         guard_band |= MGL_CLIP_LEFT;
  2889.        else if (v->bx > gcw)
  2890.         guard_band |= MGL_CLIP_RIGHT;
  2891.        if (-gcw > v->by)
  2892.         guard_band |= MGL_CLIP_BOTTOM;
  2893.        else if (v->by > gcw)
  2894.         guard_band |= MGL_CLIP_TOP;
  2895.  
  2896.        }
  2897.  
  2898.     i++;
  2899.     } while (i < poly.numverts && guard_band == 0);
  2900.    }
  2901.  
  2902.    if(polypointer == 0)
  2903.      mtexverts = 0; //reset
  2904.  
  2905.    start = mtexverts;
  2906.  
  2907.    if(or_code == 0)
  2908.    {
  2909.     if(context->ShadeModel == GL_SMOOTH)
  2910.     {
  2911.         ProjectMtex_Smooth(context, poly.numverts, mtexverts);
  2912.     }
  2913.     else
  2914.     {
  2915.         ProjectMtex_Flat(context, poly.numverts, mtexverts);
  2916.     }
  2917.  
  2918.     mtexverts += poly.numverts;
  2919.    }
  2920.    else
  2921.    {
  2922.     if(guard_band)
  2923.     {
  2924.        hc_ClipPolyFF(context, &poly, or_code);
  2925.  
  2926.        if(!poly.numverts)
  2927.         return;
  2928.     }
  2929.  
  2930.     if(context->ShadeModel == GL_SMOOTH)
  2931.     {
  2932.         for(i=0; i< poly.numverts; i++)
  2933.         {
  2934.             v_MtexToScreen_Smooth(context, poly.verts[i], mtexverts++);
  2935.         }
  2936.     }
  2937.     else
  2938.     {
  2939.         for(i=0; i< poly.numverts; i++)
  2940.         {
  2941.             v_MtexToScreen_Flat(context, poly.verts[i], mtexverts++);
  2942.         }
  2943.     }
  2944.    }
  2945.  
  2946.    pidx[polypointer].count = poly.numverts;
  2947.    pidx[polypointer].first = start;
  2948.    pidx[polypointer].tmu[0] = context->w3dTexBuffer[context->CurrentBinding];
  2949.    pidx[polypointer].tmu[1] = context->w3dTexBuffer[context->VirtualBinding];
  2950.    polypointer++;
  2951. }
  2952.  
  2953.  
  2954. void d_DrawNormalPoly(GLcontext context)
  2955. {
  2956.     int i,j;
  2957.     ULONG error;
  2958.     ULONG and_code, or_code, guard_band;
  2959.     static W3D_Vertex **verts = NULL;
  2960.     static W3D_TrianglesV fan;
  2961.     static MGLPolygon poly;
  2962.  
  2963.     if(context->VertexBufferPointer < 3)
  2964.         return;
  2965.  
  2966.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  2967.         return;
  2968.  
  2969.     v_Transform(context);
  2970.  
  2971.     and_code = 0xff; or_code = 0;
  2972.  
  2973.     for (i=0; i<context->VertexBufferPointer; i++)
  2974.     {
  2975.         MGLVertex *v = &(context->VertexBuffer[i]);
  2976.         float w = v->bw;
  2977.         ULONG outcode = 0;
  2978.  
  2979.         if (w < CLIP_EPS )
  2980.         {
  2981.             outcode |= MGL_CLIP_NEGW;
  2982.         }
  2983.  
  2984.         if (-w > v->bx)
  2985.         {
  2986.             outcode |= MGL_CLIP_LEFT;
  2987.         }
  2988.         else if (v->bx > w)
  2989.         {
  2990.             outcode |= MGL_CLIP_RIGHT;
  2991.         }
  2992.  
  2993.         if (-w > v->by)
  2994.         {
  2995.             outcode |= MGL_CLIP_BOTTOM;
  2996.         }
  2997.         else if (v->by > w)
  2998.         {
  2999.             outcode |= MGL_CLIP_TOP;
  3000.         }
  3001.     
  3002.         if (-w > v->bz)
  3003.         {
  3004.             outcode |= MGL_CLIP_BACK;
  3005.         }
  3006.         else if (v->bz > w)
  3007.         {
  3008.             outcode |= MGL_CLIP_FRONT;
  3009.         }
  3010.  
  3011.         v->outcode = outcode;
  3012.         and_code &= outcode;
  3013.         or_code |= outcode;
  3014.  
  3015.         poly.verts[i] = i;
  3016.     }
  3017.  
  3018.    if (and_code)
  3019.     return;
  3020.  
  3021.    if (verts == NULL)
  3022.    {
  3023.         verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  3024.         if (!verts) return;
  3025.    }
  3026.  
  3027.    poly.numverts = context->VertexBufferPointer;
  3028.  
  3029.  
  3030. #if defined(PRIORITIZE_BANDWIDTH) || defined(PRIORITIZE_FILRATE)
  3031.  
  3032.    //try to shrink primitive:
  3033.  
  3034.    if(context->VertexBuffer[0].outcode && poly.numverts > 3)
  3035.    {
  3036.     ULONG local_and;
  3037.     int size;
  3038.     int first;
  3039.  
  3040.     first = 0;
  3041.     i = poly.numverts - 2;
  3042.  
  3043.     local_and = context->VertexBuffer[0].outcode & context->VertexBuffer[i].outcode & context->VertexBuffer[i+1].outcode;
  3044.  
  3045.     if(local_and)
  3046.     {
  3047.         i--;
  3048.  
  3049.         while (i)
  3050.         {
  3051.            if((local_and & context->VertexBuffer[i].outcode) == 0)
  3052.             break;
  3053.  
  3054.            i--;
  3055.         }
  3056.     }
  3057.  
  3058.     size = i+2;
  3059.  
  3060.     if(size > 3)
  3061.     {
  3062.        i = 1;
  3063.  
  3064.        local_and = context->VertexBuffer[0].outcode & context->VertexBuffer[i].outcode & context->VertexBuffer[i+1].outcode;
  3065.  
  3066.        if(local_and)
  3067.        {
  3068.         i++;
  3069.  
  3070.         while (i < size-2)
  3071.         {
  3072.            if((local_and & context->VertexBuffer[i+1].outcode) == 0)
  3073.             break;
  3074.            i++;
  3075.         }
  3076.        }
  3077.  
  3078.        first = i-1;
  3079.     }
  3080.  
  3081.     if((size < poly.numverts) || first)
  3082.     {
  3083.        context->VertexBufferPointer = size;
  3084.  
  3085.        poly.numverts = size - first;
  3086.  
  3087.        or_code = context->VertexBuffer[0].outcode;
  3088.     
  3089.        i = 1;
  3090.        do
  3091.        {
  3092.         poly.verts[i] = first+i;
  3093.         or_code |= context->VertexBuffer[first+i].outcode;
  3094.  
  3095.        i++;
  3096.        } while (i < poly.numverts);
  3097.     }
  3098.    }
  3099.  
  3100. #endif
  3101.  
  3102.    if( poly.numverts == 3 && context->CullFace_State == GL_TRUE && !(or_code & MGL_CLIP_NEGW) )
  3103.    {
  3104.     if( hc_DecideFrontface(context, &context->VertexBuffer[0], &context->VertexBuffer[poly.verts[1]], &context->VertexBuffer[poly.verts[1] + 1]) == GL_FALSE)
  3105.         return;
  3106.    }
  3107.  
  3108.    PrepTexCoords(context, poly.verts[1], poly.numverts, GL_TRUE);
  3109.  
  3110.  
  3111. //guardband-test
  3112.  
  3113.    if(or_code == 0 || (or_code & context->ClipFlags))
  3114.    {
  3115.        guard_band = or_code;
  3116.    }
  3117.    else
  3118.    {
  3119.     i = 0;
  3120.     guard_band = 0;
  3121.  
  3122.     do
  3123.     {
  3124.       MGLVertex *v = &context->VertexBuffer[poly.verts[i]];
  3125.  
  3126.        if(v->outcode)
  3127.        {
  3128.        float gcw = v->bw * 2.0;
  3129.  
  3130.        if (-gcw > v->bx)
  3131.         guard_band |= MGL_CLIP_LEFT;
  3132.        else if (v->bx > gcw)
  3133.         guard_band |= MGL_CLIP_RIGHT;
  3134.        if (-gcw > v->by)
  3135.         guard_band |= MGL_CLIP_BOTTOM;
  3136.        else if (v->by > gcw)
  3137.         guard_band |= MGL_CLIP_TOP;
  3138.        }
  3139.  
  3140.     i++;
  3141.     } while (i < poly.numverts && guard_band == 0);
  3142.    }
  3143.  
  3144.  
  3145.    if(guard_band == 0)
  3146.    {
  3147.     int vert;
  3148.  
  3149.     verts[0] = &(context->VertexBuffer[0].v);
  3150.     v_ToScreen(context, 0);
  3151.  
  3152.     vert = poly.verts[1];
  3153.     i = 1;
  3154.  
  3155.     do
  3156.     {
  3157.         verts[i] = &(context->VertexBuffer[vert].v);
  3158.         v_ToScreen(context, vert);
  3159.  
  3160.     i++; vert++;
  3161.     } while (i < poly.numverts);
  3162.  
  3163.    }
  3164.    else
  3165.    {
  3166.        hc_ClipPolyFF(context, &poly, or_code);
  3167.  
  3168.        if(!poly.numverts)
  3169.         return;
  3170.  
  3171.        i=0;
  3172.  
  3173.        do
  3174.        {
  3175.         verts[i] = &(context->VertexBuffer[poly.verts[i]].v);
  3176.         v_ToScreen(context, poly.verts[i]);
  3177.  
  3178.        i++;
  3179.        } while(i < poly.numverts);
  3180.    }
  3181.  
  3182.    fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  3183.    fan.st_pattern = NULL;
  3184.    fan.vertexcount = poly.numverts;
  3185.    fan.v = verts;
  3186.  
  3187.    error = W3D_DrawTriFanV(context->w3dContext, &fan);
  3188. }
  3189.  
  3190.  
  3191. /*
  3192. surgeon: added fast path when primitive or_code equals 0
  3193. surgeon: added buffering for clipping events
  3194.  
  3195. surgeon: added a version (d_DrawTrianglesVA) that uses W3D_DrawElements/W3D_DrawArray for unclipped chains of triangles. (DrawFn) Pointer is set in GLEnd, based on the number of triangles in the pipeline.
  3196. */
  3197.  
  3198. void d_DrawTriangles(GLcontext context)
  3199. {
  3200. #if !defined(DISABLE_TRANSFORMATION)
  3201.     int i,j;
  3202.     static W3D_TriangleV tri;
  3203.     ULONG or_code, and_code;
  3204.     ULONG error;
  3205.  
  3206.     if(context->CullFace_State == GL_TRUE && context->CurrentCullFace == GL_FRONT_AND_BACK)
  3207.     return;
  3208.  
  3209.     v_Transform(context);
  3210.  
  3211.     for (i=0; i<context->VertexBufferPointer; i++)
  3212.     {
  3213.         MGLVertex *v = &(context->VertexBuffer[i]);
  3214.         float w = v->bw;
  3215.         ULONG outcode = 0;
  3216.  
  3217.         if (w < CLIP_EPS )
  3218.         {
  3219.             outcode |= MGL_CLIP_NEGW;
  3220.         }
  3221.  
  3222.         if (-w > v->bx)
  3223.         {
  3224.             outcode |= MGL_CLIP_LEFT;
  3225.         }
  3226.         else if (v->bx > w)
  3227.         {
  3228.             outcode |= MGL_CLIP_RIGHT;
  3229.         }
  3230.  
  3231.         if (-w > v->by)
  3232.         {
  3233.             outcode |= MGL_CLIP_BOTTOM;
  3234.         }
  3235.         else if (v->by > w)
  3236.         {
  3237.             outcode |= MGL_CLIP_TOP;
  3238.         }
  3239.     
  3240.         if (-w > v->bz)
  3241.         {
  3242.             outcode |= MGL_CLIP_BACK;
  3243.         }
  3244.         else if (v->bz > w)
  3245.         {
  3246.             outcode |= MGL_CLIP_FRONT;
  3247.         }
  3248.  
  3249.         v->outcode = outcode;
  3250.     }
  3251.  
  3252.  
  3253.     tri.tex = context->w3dTexBuffer[context->CurrentBinding];
  3254.     tri.st_pattern = NULL;
  3255.  
  3256.  
  3257.     for (i=0; i<context->VertexBufferPointer; i+=3)
  3258.     {
  3259.        or_code = context->VertexBuffer[i+0].outcode
  3260.                 | context->VertexBuffer[i+1].outcode
  3261.                 | context->VertexBuffer[i+2].outcode;
  3262.  
  3263.        and_code = context->VertexBuffer[i+0].outcode
  3264.                  & context->VertexBuffer[i+1].outcode
  3265.                  & context->VertexBuffer[i+2].outcode;
  3266.  
  3267.        if (and_code)
  3268.         continue;
  3269.  
  3270.        if(context->CullFace_State == GL_TRUE && !(or_code & MGL_CLIP_NEGW))
  3271.        {
  3272.         if (hc_DecideFrontface(context,
  3273.         &(context->VertexBuffer[i+0]),
  3274.         &(context->VertexBuffer[i+1]),
  3275.         &(context->VertexBuffer[i+2])) == GL_FALSE)
  3276.             continue;
  3277.        }
  3278.  
  3279.        PrepTexCoords(context, i, 3, GL_FALSE);
  3280.  
  3281.        if (or_code == 0)
  3282.        {
  3283.         v_ToScreen(context, i+0);
  3284.         v_ToScreen(context, i+1);
  3285.         v_ToScreen(context, i+2);
  3286.  
  3287.         tri.v1 = &(context->VertexBuffer[i+0].v);
  3288.         tri.v2 = &(context->VertexBuffer[i+1].v);
  3289.         tri.v3 = &(context->VertexBuffer[i+2].v);
  3290.  
  3291.         error = W3D_DrawTriangleV(context->w3dContext, &tri);
  3292.        }
  3293.        else
  3294.        {
  3295.         static MGLPolygon poly;
  3296.         poly.numverts = 3;
  3297.         poly.verts[0] = i+0;
  3298.         poly.verts[1] = i+1;
  3299.         poly.verts[2] = i+2;
  3300.  
  3301.         hc_ClipAndDrawPoly(context, &poly, or_code);
  3302.        }
  3303.     }
  3304. #else
  3305.     int i;
  3306.     static W3D_TriangleV tri;
  3307.     ULONG error;
  3308.  
  3309.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  3310.  
  3311.     for (i=0; i<context->VertexBufferPointer; i+=3)
  3312.     {
  3313.         v_ToScreen(context, i);
  3314.         v_ToScreen(context, i+1);
  3315.         v_ToScreen(context, i+2);
  3316.  
  3317.         tri.v1 = &(context->VertexBuffer[i+0].v);
  3318.         tri.v2 = &(context->VertexBuffer[i+1].v);
  3319.         tri.v3 = &(context->VertexBuffer[i+2].v);
  3320.         tri.tex = context->w3dTexBuffer[context->CurrentBinding];
  3321.         tri.st_pattern = NULL;
  3322.         error = W3D_DrawTriangleV(context->w3dContext, &tri);
  3323.     }
  3324. #endif
  3325. }
  3326.  
  3327. void d_DrawTrianglesVA(GLcontext context)
  3328. {
  3329.     int i,j;
  3330.     ULONG or_code, and_code;
  3331.     ULONG error;
  3332.     ULONG vcount;    //counter for vertices
  3333.     GLbitfield ClientState;
  3334.     GLboolean continous;
  3335.     GLfloat sign;
  3336.     UWORD *vaindex;
  3337.  
  3338.     v_Transform(context);
  3339.  
  3340.     for (i=0; i<context->VertexBufferPointer; i++)
  3341.     {
  3342.         MGLVertex *v = &(context->VertexBuffer[i]);
  3343.         float w = v->bw;
  3344.         ULONG outcode = 0;
  3345.  
  3346.         if (w < CLIP_EPS )
  3347.         {
  3348.             outcode |= MGL_CLIP_NEGW;
  3349.         }
  3350.  
  3351.         if (-w > v->bx)
  3352.         {
  3353.             outcode |= MGL_CLIP_LEFT;
  3354.         }
  3355.         else if (v->bx > w)
  3356.         {
  3357.             outcode |= MGL_CLIP_RIGHT;
  3358.         }
  3359.  
  3360.         if (-w > v->by)
  3361.         {
  3362.             outcode |= MGL_CLIP_BOTTOM;
  3363.         }
  3364.         else if (v->by > w)
  3365.         {
  3366.             outcode |= MGL_CLIP_TOP;
  3367.         }
  3368.     
  3369.         if (-w > v->bz)
  3370.         {
  3371.             outcode |= MGL_CLIP_BACK;
  3372.         }
  3373.         else if (v->bz > w)
  3374.         {
  3375.             outcode |= MGL_CLIP_FRONT;
  3376.         }
  3377.  
  3378.         v->outcode = outcode;
  3379.     }
  3380.  
  3381.     vcount = 0;
  3382.     vaindex = &context->ElementIndex[0];
  3383.  
  3384.     continous = GL_TRUE; //decide drawfunc
  3385.     sign = (GLfloat)-context->CurrentCullSign;
  3386.  
  3387.     for (i=0; i<context->VertexBufferPointer; i+=3)
  3388.     {
  3389.        or_code = context->VertexBuffer[i+0].outcode
  3390.                 | context->VertexBuffer[i+1].outcode
  3391.                 | context->VertexBuffer[i+2].outcode;
  3392.  
  3393.        and_code = context->VertexBuffer[i+0].outcode
  3394.                  & context->VertexBuffer[i+1].outcode
  3395.                  & context->VertexBuffer[i+2].outcode;
  3396.  
  3397.        if (and_code)
  3398.        {
  3399.         continous = GL_FALSE;
  3400.         continue;
  3401.        }
  3402.  
  3403.        if (or_code == 0)
  3404.        {
  3405.         v_ToScreenVA(context, i+0);
  3406.         v_ToScreenVA(context, i+1);
  3407.         v_ToScreenVA(context, i+2);
  3408.  
  3409.         if(context->CullFace_State == GL_TRUE)
  3410.         {
  3411.            GLfloat x1,x2,y1,y2;
  3412.            GLfloat area;
  3413.  
  3414.            #define x(a) (context->VertexBuffer[a].bx)
  3415.            #define y(a) (context->VertexBuffer[a].by)
  3416.  
  3417.            x1 = x(i+1) - x(i);
  3418.            y1 = y(i+1) - y(i);
  3419.            x2 = x(i+2) - x(i);
  3420.            y2 = y(i+2) - y(i);
  3421.  
  3422.            area = (y2*x1 - x2*y1) * sign;
  3423.  
  3424.            if (area < context->MinTriArea)
  3425.            {
  3426.             continous = GL_FALSE;
  3427.             continue;
  3428.            }
  3429.  
  3430.            #undef x
  3431.            #undef y
  3432.         }
  3433.  
  3434.             //build index for W3D_DrawElements
  3435.  
  3436.         vaindex[vcount+0] = i+0;
  3437.         vaindex[vcount+1] = i+1;
  3438.         vaindex[vcount+2] = i+2;
  3439.         vcount += 3;
  3440.        }
  3441.          else
  3442.        {
  3443.         static MGLPolygon poly;
  3444.  
  3445.         continous = GL_FALSE;
  3446.  
  3447.         if(context->CullFace_State == GL_TRUE && !(or_code & MGL_CLIP_NEGW))
  3448.         {
  3449.             if (hc_DecideFrontface(context, &(context->VertexBuffer[i+0]), &(context->VertexBuffer[i+1]), &(context->VertexBuffer[i+2])) == GL_FALSE)
  3450.             continue;
  3451.         }
  3452.  
  3453.             PrepTexCoords(context, i, 3, GL_FALSE);
  3454.  
  3455.         poly.numverts = 3;
  3456.         poly.verts[0] = i+0;
  3457.         poly.verts[1] = i+1;
  3458.         poly.verts[2] = i+2;
  3459.  
  3460.         hc_ClipAndDrawPoly(context, &poly, or_code);
  3461.        }
  3462.     }
  3463.  
  3464.     ClientState = GLCS_VERTEX;
  3465.  
  3466.     if(context->Texture2D_State[0] == GL_FALSE)
  3467.     {
  3468.         Set_W3D_Texture(context->w3dContext, 0, NULL);
  3469.     }
  3470.     else
  3471.     {
  3472.         ClientState |= GLCS_TEXTURE;
  3473.  
  3474.         Set_W3D_Texture(context->w3dContext, 0, context->w3dTexBuffer[context->CurrentBinding]);
  3475.  
  3476.         Set_W3D_TexCoordPointer(context->w3dContext, (void*)&(context->VertexBuffer->v.u), sizeof(MGLVertex), 0, 4, -4, W3D_TEXCOORD_NORMALIZED);
  3477.     }
  3478.  
  3479.     Set_W3D_VertexPointer(context->w3dContext, (void*)&(context->VertexBuffer->bx), sizeof(MGLVertex), W3D_VERTEX_F_F_F, 0);
  3480.  
  3481.     if(context->ShadeModel == GL_SMOOTH)
  3482.     {
  3483.         ClientState |= GLCS_COLOR;
  3484.  
  3485.         Set_W3D_ColorPointer(context->w3dContext, (void*)&(context->VertexBuffer->v.color.r), sizeof(MGLVertex), W3D_COLOR_FLOAT, W3D_CMODE_RGBA, 0);
  3486.     }
  3487.  
  3488.  
  3489. // draw with fastest method
  3490.  
  3491.     if(continous == GL_TRUE)
  3492.     {
  3493.         error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, 0, context->VertexBufferPointer);
  3494.     }
  3495.     else
  3496.     {
  3497.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, W3D_INDEX_UWORD, vcount, (void*)&vaindex[0]);
  3498.     }
  3499.  
  3500.     Reset_W3D_ArrayPointers(context, ClientState);
  3501.  
  3502. }
  3503.  
  3504.  
  3505. /*
  3506. ** A MGL_FLATFAN / MGL_FLATSTRIP is a triangle fan or strip
  3507. ** that is specified in device corrdinates and is drawn
  3508. ** regardless of current matrix or viewport
  3509. **
  3510. ** Very useful for bypassing the transformation pipeline 
  3511. **
  3512. */
  3513.  
  3514. void d_DrawFlat(GLcontext context)
  3515. {
  3516.     ULONG error;
  3517.  
  3518.     int i;
  3519.  
  3520.     static W3D_Vertex *verts[MGL_MAXVERTS];
  3521.     static W3D_TrianglesV tris;
  3522.  
  3523.     PrepTexCoords(context, 0, context->VertexBufferPointer, GL_FALSE);
  3524.  
  3525.     for (i=0; i<context->VertexBufferPointer; i++)
  3526.     {
  3527.     verts[i] = &context->VertexBuffer[i].v;
  3528.  
  3529.     context->VertexBuffer[i].v.x = (W3D_Float) context->VertexBuffer[i].bx;
  3530.     context->VertexBuffer[i].v.y = (W3D_Float) context->VertexBuffer[i].by;
  3531.     context->VertexBuffer[i].v.z = (W3D_Double) context->VertexBuffer[i].bz;
  3532.     context->VertexBuffer[i].v.w = (W3D_Float) context->VertexBuffer[i].bw;
  3533.  
  3534.     }
  3535.  
  3536.     tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  3537.     tris.st_pattern = NULL;
  3538.     tris.v = verts;
  3539.     tris.vertexcount = context->VertexBufferPointer;
  3540.  
  3541.     #ifndef NODRAW
  3542.  
  3543.     if(context->CurrentPrimitive == MGL_FLATSTRIP)
  3544.     {
  3545.         error = W3D_DrawTriStripV(context->w3dContext, &tris);
  3546.     }
  3547.     else //MGL_FLATFAN
  3548.     {
  3549.         error = W3D_DrawTriFanV(context->w3dContext, &tris);
  3550.     }
  3551.  
  3552.     #endif
  3553. }
  3554.  
  3555.  
  3556. void dh_DrawPoly(GLcontext context, MGLPolygon *poly)
  3557. {
  3558.     int i;
  3559.     ULONG error;
  3560.     static W3D_Vertex *verts[8];//max clipverts for quad
  3561.     static W3D_TrianglesV tris;
  3562.  
  3563.     for (i=0; i<poly->numverts; i++)
  3564.     {
  3565.         v_ToScreen(context, poly->verts[i]);
  3566.         verts[i] = &(context->VertexBuffer[poly->verts[i]].v);
  3567.     }
  3568.  
  3569.     tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  3570.     tris.st_pattern = NULL;
  3571.     tris.vertexcount = poly->numverts;
  3572.     tris.v = verts;
  3573.     #ifndef NODRAW
  3574.     error = W3D_DrawTriFanV(context->w3dContext, &tris);
  3575.     #endif
  3576. }
  3577.  
  3578.  
  3579. /*
  3580. ** See below for the interface to MiniGL/OpenGL
  3581. */
  3582.  
  3583. static void d_DrawMtexPolyChains(GLcontext context, GLuint unit, GLuint size)
  3584. {
  3585.     int i;
  3586.     ULONG error;
  3587.  
  3588.     if(unit == 0)
  3589.     {
  3590.         i = 0;
  3591.         do
  3592.         {
  3593.             Set_W3D_Texture(context->w3dContext, 0, pidx[i].tmu[0]);
  3594.  
  3595.             error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIFAN, pidx[i].first, pidx[i].count);
  3596.  
  3597.         i++;
  3598.         } while(i < size);
  3599.     }
  3600.     else
  3601.     {
  3602.         i = 0;
  3603.         do
  3604.         {
  3605.             Set_W3D_Texture(context->w3dContext, 0, pidx[i].tmu[1]);
  3606.  
  3607.             error = W3D_DrawArray(context->w3dContext, W3D_PRIMITIVE_TRIFAN, pidx[i].first, pidx[i].count);
  3608.  
  3609.         i++;
  3610.         } while(i < size);
  3611.     }
  3612. }
  3613.  
  3614. /*
  3615. **
  3616.  
  3617. MiniGL API:
  3618.  
  3619. mglDrawMultitexBuffer(GLenum bs, GLenum bd, GLenum env)
  3620.  
  3621. where bs = BlendSrc, bd = BlendDst, env = TexEnv
  3622.  
  3623. This function should be called when all polys are in chain or a global state change make it required.
  3624. It sets the supplied state-parameters, draws the buffer, and returns the context as it was before.
  3625.  
  3626.  
  3627. **
  3628. */
  3629.  
  3630. void MGLDrawMultitexBuffer (GLcontext context, GLenum BSrc, GLenum BDst, GLenum TexEnv)
  3631. {
  3632.     GLboolean blendfunc_changed;
  3633.     GLboolean depthmask_changed;
  3634.     GLbitfield ClientState;
  3635.     GLenum CurBlendSrc, CurBlendDst;
  3636.  
  3637.     if(polypointer == 0)
  3638.         return;
  3639.  
  3640. #ifdef AUTOMATIC_LOCKING_ENABLE
  3641.  
  3642.     if (context->LockMode != MGL_LOCK_MANUAL)
  3643.     { 
  3644.        if (context->LockMode == MGL_LOCK_AUTOMATIC) // Automatic: Lock per primitive
  3645.        {
  3646.         if (W3D_SUCCESS == W3D_LockHardware(context->w3dContext))
  3647.         {
  3648.             context->w3dLocked = GL_TRUE;
  3649.         }
  3650.         else
  3651.         {
  3652.                   printf("Error during LockHardware\n");
  3653.         }
  3654.        }
  3655.        else // Smart: Lock timer based
  3656.        {
  3657.         if (context->w3dLocked == GL_FALSE)
  3658.         {
  3659.             if (W3D_SUCCESS != W3D_LockHardware(context->w3dContext))
  3660.             {
  3661.                 return; // give up
  3662.              }
  3663.  
  3664.             context->w3dLocked = GL_TRUE;
  3665.  
  3666.             TMA_Start(&(context->LockTime));
  3667.         }
  3668.        }
  3669.     }
  3670.  
  3671. #endif
  3672.  
  3673.     if (context->FogDirty && context->Fog_State)
  3674.     {
  3675.         fog_Set(context);
  3676.         context->FogDirty = GL_FALSE;
  3677.     }
  3678.  
  3679.     if(context->CurTexEnv != TexEnv)
  3680.     {
  3681.         W3D_Texture *tex = pidx[0].tmu[1];
  3682.  
  3683.         switch(TexEnv)
  3684.         {
  3685.         case GL_MODULATE:
  3686.             W3D_SetTexEnv(context->w3dContext, tex, W3D_MODULATE, NULL);
  3687.             break;
  3688.         case GL_DECAL:
  3689.             W3D_SetTexEnv(context->w3dContext, tex, W3D_DECAL, NULL);
  3690.             break;
  3691.         default:
  3692.         case GL_REPLACE:
  3693.             W3D_SetTexEnv(context->w3dContext, tex, W3D_REPLACE, NULL);
  3694.             break;
  3695.         }
  3696.     }
  3697.  
  3698.     if(context->CurBlendSrc != BSrc || context->CurBlendDst != BDst)
  3699.     {
  3700.         CurBlendSrc = context->CurBlendSrc;
  3701.         CurBlendDst = context->CurBlendDst;
  3702.  
  3703.            GLBlendFunc(context, BSrc, BDst);
  3704.         blendfunc_changed = GL_TRUE;
  3705.     }
  3706.     else
  3707.     {
  3708.         blendfunc_changed = GL_FALSE;
  3709.     }
  3710.  
  3711.     //set vertexpointer to the multitexturebuffer
  3712.  
  3713.     Set_W3D_VertexPointer(context->w3dContext, (void*)&mtex_pbuffer[0].x, sizeof(W3D_VAVertex), W3D_VERTEX_F_F_F, 0); 
  3714.  
  3715.     //set the texcoordpointer to tmu0 coords:
  3716.  
  3717.     Set_W3D_TexCoordPointer(context->w3dContext, (void*)&mtex_pbuffer[0].s1, sizeof(W3D_VAVertex), 0, 4, -4, W3D_TEXCOORD_NORMALIZED);
  3718.  
  3719.  
  3720.     if(context->ShadeModel == GL_FLAT && context->UpdateCurrentColor == GL_TRUE)
  3721.     {
  3722.         W3D_SetCurrentColor(context->w3dContext, &context->CurrentColor);
  3723.         context->UpdateCurrentColor = GL_FALSE;
  3724.     }
  3725.     else if(context->ShadeModel == GL_SMOOTH)
  3726.     {
  3727.         Set_W3D_ColorPointer(context->w3dContext, (void*)&mtex_pbuffer[0].color, sizeof(W3D_VAVertex), W3D_COLOR_UBYTE, W3D_CMODE_ARGB, 0); 
  3728.     }
  3729.  
  3730.     //draw the buffered primitives for tmu[0]
  3731.  
  3732.     d_DrawMtexPolyChains(context, 0, polypointer);
  3733.  
  3734. #if 0
  3735.     //Disable Zbuffer updates for second pass
  3736.  
  3737.     if(context->DepthMask == GL_TRUE)
  3738.     {
  3739.         W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_DISABLE);
  3740.  
  3741.         depthmask_changed = GL_TRUE;
  3742.     }
  3743.     else
  3744.     {
  3745.         depthmask_changed = GL_FALSE;
  3746.     }
  3747. #endif
  3748.  
  3749.     //switch the texcoordpointer to tmu1 coords:
  3750.  
  3751.     Set_W3D_TexCoordPointer(context->w3dContext, (void*)&mtex_pbuffer[0].s2, sizeof(W3D_VAVertex), 0, 4, -12, W3D_TEXCOORD_NORMALIZED);
  3752.  
  3753.     //draw the buffered primitives for tmu[1] with blending enabled:
  3754.  
  3755.     ENABLE_BLEND
  3756.  
  3757.     d_DrawMtexPolyChains(context, 1, polypointer);
  3758.  
  3759.     DISABLE_BLEND
  3760.  
  3761.     polypointer = 0; //reset the buffer
  3762.  
  3763.     //restore vertexpointers to their previous position
  3764.  
  3765.     ClientState = GLCS_VERTEX | GLCS_TEXTURE;
  3766.  
  3767.     if(context->ShadeModel == GL_SMOOTH)
  3768.     {
  3769.         ClientState |= GLCS_COLOR;
  3770.     }
  3771.  
  3772.     Reset_W3D_ArrayPointers(context, ClientState);
  3773.  
  3774. #if 0
  3775.     if(depthmask_changed == GL_TRUE)
  3776.     {
  3777.         W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE);
  3778.     }
  3779. #endif
  3780.  
  3781.     //reset states to entry-level
  3782.  
  3783.     if(blendfunc_changed == GL_TRUE)
  3784.     {
  3785.         GLBlendFunc(context, CurBlendSrc, CurBlendDst);
  3786.     }
  3787.  
  3788.     if(context->CurTexEnv != TexEnv)
  3789.     {
  3790.         W3D_Texture *tex = pidx[0].tmu[1];
  3791.  
  3792.         switch(context->CurTexEnv)
  3793.         {
  3794.         case GL_MODULATE:
  3795.             W3D_SetTexEnv(context->w3dContext, tex, W3D_MODULATE, NULL);
  3796.             break;
  3797.         case GL_DECAL:
  3798.             W3D_SetTexEnv(context->w3dContext, tex, W3D_DECAL, NULL);
  3799.             break;
  3800.         default:
  3801.         case GL_REPLACE:
  3802.             W3D_SetTexEnv(context->w3dContext, tex, W3D_REPLACE, NULL);
  3803.             break;
  3804.         }
  3805.     }
  3806.  
  3807. #ifdef AUTOMATIC_LOCKING_ENABLE
  3808.  
  3809.     if(context->LockMode != MGL_LOCK_MANUAL)
  3810.     {
  3811.        if(context->LockMode == MGL_LOCK_AUTOMATIC)
  3812.        {
  3813.         W3D_UnLockHardware(context->w3dContext);
  3814.         context->w3dLocked = GL_FALSE;
  3815.        }
  3816.        else if (context->LockMode == MGL_LOCK_SMART && TMA_Check(&(context->LockTime)) == GL_TRUE)
  3817.        {
  3818.         // Time to unlock
  3819.         W3D_UnLockHardware(context->w3dContext);
  3820.         context->w3dLocked = GL_FALSE;
  3821.        }
  3822.     }
  3823.  
  3824. #endif
  3825.  
  3826. }
  3827.  
  3828. #ifdef __VBCC__
  3829.  
  3830.     #undef v_ToScreen
  3831.     #undef v_ToScreenVA
  3832.  
  3833. #endif
  3834.